更改时自动调整相关状态,反之亦然

时间:2016-10-18 08:52:24

标签: javascript reactjs calendar redux

所以我使用Airbnb的react-dates库来制作日历:

组件

export const Calendar = ({setDates, startDate, endDate, setFocused, focusedInput}) => {
return (
    <div className="input-group">
        <div className="input-group_addon">
            <i className="icon-date-inactive" aria-hidden="true"></i>
        </div>
        <DateRangePicker
            startDate={startDate}
            endDate={endDate}
            focusedInput={focusedInput}
            displayFormat="ddd, D MMM"
            onDatesChange={setDates}
            onFocusChange={setFocused}
        />
    </div>
    )
}

容器

const mapStateToProps = (state) => {
    return {
        startDate: state.model.model.calendar.startDate,
        endDate: state.model.model.calendar.endDate,
        focusedInput: state.model.model.calendar.focusedInput
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        setDates: (dates) => {
            dispatch(marketplaceSetDates(dates.startDate, dates.endDate));
        },
        setFocused: (focusedInput) => {
            dispatch(marketplaceSetFocused(focusedInput));
        }
    }
}

export const CalendarContainer = connect(mapStateToProps, mapDispatchToProps)(Calendar);

操作

export function marketplaceSetDates(startDate, endDate) {
    return {
        type: 'MARKETPLACE_MODEL_DATES_CHANGE',
        dates: {
            start: startDate,
            end: endDate
        }
    }
}

export function marketplaceSetFocused(focusedInput) {
    return {
        type: 'MARKETPLACE_MODEL_FOCUS_CHANGE',
        focusedInput: focusedInput
    }
}

减速

let initialState = {
    model: {
        calendar: {
            startDate: moment().add(1, 'day'),
            endDate: moment().add(4, 'day'),
            focusedInput: null
        }
    },
}

export const modelReducer = (state = initialState, action) => {
    let newState = {};
    switch(action.type) {
        case 'MARKETPLACE_MODEL_FOCUS_CHANGE':
            newState = Object.assign({}, state);
            newState.model.calendar.focusedInput = action.focusedInput;
            return newState;

        case 'MARKETPLACE_MODEL_DATES_CHANGE':
            newState = Object.assign({}, state);

            newState.model.calendar.startDate = (action.dates.start === null) ?
            state.model.calendar.startDate : action.dates.start;

            newState.model.calendar.endDate = (action.dates.end === null) ?
            state.model.calendar.startDate.add(4, 'day') : action.dates.end;

            return newState;
    }
    return state;
}

我们日历的一条规则是,每当用户选择新的startDateendDate时,它必须自动调整为至少相隔3天

例如,正如您所看到的,初始状态将日期设置为明天和之后的4天。

  • 所以它将是 10月19日 - &gt; 10月22日
  • 如果我点击 10月24日上的新startDate (请注意,它不在前一天的范围内),那么{ {1}}必须自动调整为 10月27日
  • 在所选范围之前点击endDate时也是如此,endDate必须在所选startDate前3天相应地自动调整。

但是使用我当前的代码,当我点击endDate时, startDatestartDate都设置为后3天,这应该只是endDate的价值。

我怀疑这背后的原因是由于endDate中的状态变异是异步的,因此reduxstate.model.calendar.startDate.add(4, 'day')之前先行,我的假设是否正确?

否则,我想帮助解决方法。

1 个答案:

答案 0 :(得分:2)

TL; DR: 将添加天数功能更改为: state.model.calendar.startDate.clone().add(4, 'day')

我认为这个问题与momentjs添加功能有关。 来自文档: http://momentjs.com/docs/#/manipulating/add/

  

添加

     

...   通过增加时间来改变原始时刻。

这意味着当你这样做时 state.model.calendar.startDate.add(4, 'day')它实际上会更改state.model.calendar.startDate的值。

理想情况下,您应该复制片刻,然后使用clone()

进行更改