import React, { useRef, Fragment, useState, useEffect, useCallback, useImperativeHandle, forwardRef, } from 'react'; import { Image, Text, TouchableOpacity, View } from 'react-native'; import XDate from 'xdate'; import PropTypes from 'prop-types'; import { dateToStringFormat, parseDate, isSameMonth, dateResource, isLeftMonthBig, } from './utils'; import Style from './style'; import type { Direction, IMonthSwitchProps, IMonthSwitchRef } from './types'; const MonthSwitch = forwardRef( (props, ref) => { const { format, maxDate, onChange, initValue, arrowStyle, onLeftArrow, onRightArrow, maxDateTrigger, renderCustomArrow, } = props; const styles = useRef(Style()); const isMounted = useRef(false); useImperativeHandle(ref, () => ({ reset: () => reset(), })); const [currentMonth, setCurrentMonth] = useState( initValue ? parseDate(initValue) : new XDate() ); useEffect(() => { if (initValue) { setCurrentMonth(parseDate(initValue)); } }, [initValue]); useEffect(() => { if (isMounted.current) { onChange && onChange(dateResource(currentMonth)); } else { isMounted.current = true; } }, [currentMonth, onChange]); const updateCurrentMonth = useCallback( (newMonth: XDate) => { if (isSameMonth(newMonth, currentMonth)) { return; } setCurrentMonth(newMonth); }, [currentMonth] ); const updateMonth = useCallback( (count: number, onArrowChange?: (date: string) => void) => { const newMonth = currentMonth.clone().addMonths(count, true); if (maxDate && !isLeftMonthBig(newMonth, new XDate(maxDate))) { maxDateTrigger && maxDateTrigger(true); return; } updateCurrentMonth(newMonth); onArrowChange && onArrowChange(dateToStringFormat(newMonth)); }, [currentMonth, maxDate, maxDateTrigger, updateCurrentMonth] ); const _onLeftArrow = useCallback(() => { updateMonth(-1, onLeftArrow); }, [onLeftArrow, updateMonth]); const _onRightArrow = useCallback(() => { updateMonth(1, onRightArrow); }, [onRightArrow, updateMonth]); const reset = useCallback(() => { setCurrentMonth(initValue ? parseDate(initValue) : new XDate()); }, [initValue]); const renderArrow = (direction: Direction) => { const isLeft = direction === 'left'; const ArrowDirection = isLeft ? 'left' : 'right'; const arrowImage = isLeft ? require('./images/left.png') : require('./images/right.png'); const onPress = isLeft ? _onLeftArrow : _onRightArrow; return ( {renderCustomArrow ? ( renderCustomArrow(ArrowDirection) ) : ( )} ); }; const renderDate = () => { return ( {currentMonth.toString(format)} ); }; return ( {renderArrow('left')} {renderDate()} {renderArrow('right')} ); } ); export default MonthSwitch; MonthSwitch.displayName = 'MonthSwitch'; MonthSwitch.propTypes = { format: PropTypes.string, onChange: PropTypes.func, maxDate: PropTypes.string, initValue: PropTypes.string, onLeftArrow: PropTypes.func, onRightArrow: PropTypes.func, arrowStyle: PropTypes.object, maxDateTrigger: PropTypes.func, renderCustomArrow: PropTypes.func, }; MonthSwitch.defaultProps = { format: 'yyyy-MM', };