Javascript ReactJS+;Fluxxor级联操作导致错误
我有一个父组件,它有两个子组件 更新Javascript ReactJS+;Fluxxor级联操作导致错误,javascript,reactjs,reactjs-flux,flux,Javascript,Reactjs,Reactjs Flux,Flux,我有一个父组件,它有两个子组件 更新 我重写了一些语句和代码,使其更易于理解 父项:ReservationFormComponent 子项:ReservationTypePanel&ReservationCalendarPanel 父组件ReservationFormComponent最初仅显示ReservationTypePanel。另一个同级ReservationCalendarPanel隐藏,直到在ReservationTypePanel上选择了一个项目 因此,问题是当在Reservati
我重写了一些语句和代码,使其更易于理解 父项:
ReservationFormComponent
子项:
ReservationTypePanel
&ReservationCalendarPanel
父组件ReservationFormComponent
最初仅显示ReservationTypePanel
。另一个同级ReservationCalendarPanel
隐藏,直到在ReservationTypePanel
上选择了一个项目
因此,问题是当在ReservationTypePanel
中选择项目时,ReservationCalendarPanel
将使用在ReservationFormStore
存储中设置的初始值进行渲染。特别是
initialize: function(){
this.reservationType = void 8;
this.pickupTime = moment().add('minutes',30);
}
因此,当呈现ReservationCalendarPanel
时,其子组件DateTimeField
接受状态pickupTime
将重新呈现,并触发调用另一个操作的onChange
事件
return DateTimeField({
pickupTime: pickupTime,
onChange: function(time){
// Here is where the action gets called again
this$.getFlux().actions.setReservationPickupTime(time);
}
});
并向我问候此错误未捕获错误:无法在发送另一个操作时发送操作
我已经尽力删减了下面的代码。我没有使用JSX
,因为原始代码在LiveScript
中,所以我只是将编译后的代码显示在这里
这是父组件ReservationFormComponent
ReservationFormComponent = React.createClass({
get flux(){ // Instantiating Fluxxor
return new Fluxxor.Flux({ // These are the stores
'reservation-form': new ReservationFormStore,
'reservation-types': new ReservationTypeStore
}, { // These are the actions
setReservationType: function(value){
return this.dispatch('SET_RESERVATION_TYPE', value);
},
setReservationPickupTime: function(value){
return this.dispatch('SET_RESERVATION_PICKUP_TIME', value);
}
});
},
componentWillMount: function(){
this.flux.store('reservation-form').addListener('change', this.onChange);
},
onChange: function(){ // This triggers the re-render to display the ReservationCalendarPanel
this.setState({
pickupTime: this.flux.store('reservation-form').pickupTime
});
},
render: function() {
reservationType = this.state.reservationType;
return form({
className: 'container'
}, ReservationTypePanel({
flux: this.flux
}), reservationType ? ReservationCalendarPanel({
flux: this.flux
}) : null // This conditional to mount or not mount the component
);
}
});
ReservationTypePanel
组件。在这里,呈现的组件侦听onClick
事件并分派setReservationType
操作
ReservationTypePanel = React.createClass({
mixins: [fluxxor.FluxMixin(react)],
onSelectReservationType: function(reservationType){
var this$ = this;
return function(event){
this$.getFlux().actions.setReservationType(reservationType);
};
},
render: function() {
var this$ = this;
return ReservationTypeItem({
onClick: this$.onSelectReservationType(type);
})
}
});
ReservationCalendarPanel
组件。这里是DateTimeField被呈现的地方,它从ReservationFormStore
接收状态,并设置导致另一个分派的值。这就是错误的来源
ReservationCalendarPanel = React.createClass({
mixins: [fluxxor.FluxMixin(react)],
getInitialState: function() {
return {pickupTime: moment()} // sets the current time
},
componentWillMount: function(){
this.getFlux().store('reservation-form').addListener('change-pickup-time', this.onFlux);
},
componentWillUnmount: function(){
this.getFlux().store('reservation-form').removeListener('change-pickup-time', this.onFlux);
},
render: function() {
var this$ = this;
if (this.state.pickupTime) {
pickupTime = moment(this.state.pickupTime);
}
return DateTimeField({
date: pickupTime,
onChange: function(time){
// Here is where the action gets called again
this$.getFlux().actions.setReservationPickupTime(time);
}
});
});
这是DateTimeField
这是
DateTimeField = React.createClass({
getInitialState: function(){
return {
text: ''
};
},
componentWillReceiveProps: function(nextProps){
this.setDate(nextProps.date);
},
componentDidMount: function(){
$(this.getDOMNode()).datepicker()
.on('changeDate', this.onChangeDate)
.on('clearDate', this.onChangeDate);
this.setDate(this.props.date);
},
componentWillUnmount: function(){
return $(this.getDOMNode()).datepicker('remove');
},
getDatepickerDate: function(){
return $(this.getDOMNode()).datepicker('getDate');
},
setDate: function(date){
if (!this.isMounted()) {
return;
}
if (moment(date).isSame(this.getDatepickerDate, 'day')) {
// If there is no change between the date that
// is about to be set then just ignore and
// keep the old one.
return;
}
date = date ? moment(date).toDate() : void 8;
$(this.getDOMNode()).datepicker('setDate', date);
},
onChangeDate: function(event){
if (this.props.onChange) {
this.props.onChange(event.date);
}
},
render: function(){
return this.transferPropsTo(input({
type: 'text',
className: 'form-control'
}));
}
});
如果这里是商店:
ReservationFormStore = fluxxor.createStore({
actions: {
SET_RESERVATION_TYPE: 'setReservationType',
SET_RESERVATION_PICKUP_TIME: 'setPickupTime'
},
initialize: function(){
this.reservationType = void 8;
this.pickupTime = moment().add('minutes',30);
},
setReservationType: function(reservationType){
this.reservationType = reservationType;
this.reservationTypeValidate = true;
this.emit('change-reservation-type', this.reservationType);
this.emit('change');
}
setPickupTime: function(pickupTime){
this.pickupTime = pickupTime;
this.pickupTimeValidate = true;
this.emit('change-pickup-time', this.pickupTime);
this.emit('change');
}
});
看起来每个动作分派都发生在
onChange
处理程序中,因此它们不应该级联,除非DateTimeField
在呈现后立即调用onChange
。如果是这种情况,pickupTime
应该在存储中初始化,并在ReservationCalendarPanel
中接收,然后以某种方式传递到DateTimeField
。如果我不正确,请为DateTimeField
添加代码。您还可以查看是否使用帮助。@BinaryMuse感谢您的回复。似乎datetime字段
在呈现后立即触发onChange
事件。我将添加代码。此外,我还重写了问题,并对代码进行了重构,使其更易于理解。请注意,ReservationCalendarPanel
最初并没有装入,只有在选择了ReservationTypePanel
中的项目时才会装入。我已经看到了您提到的批量更新,但我正试图找出导致此问题的原因以及解决方法。我目前正在运行0.10
版本的React
,因此我无法利用batchUpdate atm。我不确定我是否完全理解您的代码流程,但我注意到有一点可以改进,可能会有所帮助:在setDate()
函数中,您实际上更改了输入date
变量,使用语句date=date?片刻…
。更好:创建一个新的var tempDate
变量并将其传递给日期选择器。因为setDate()
也通过this.props.date
调用,您不应该更改props。