Javascript 将Flux store中的Immutable.js映射与内部React组件状态合并

Javascript 将Flux store中的Immutable.js映射与内部React组件状态合并,javascript,reactjs,reactjs-flux,flux,immutable.js,Javascript,Reactjs,Reactjs Flux,Flux,Immutable.js,我一直在慢慢地将React+Flux应用程序转换为使用Immutable.js数据结构。我使用Flux的原始、香草FB实现 我遇到的一个问题是将组件状态与从通量存储接收到的状态混合 我将所有重要的业务逻辑状态保存在商店中。但我的规则是在组件中保持与UI相关的状态。例如,商店不需要担心下拉菜单是否打开,对吗 当在组件中执行的操作改变了同一组件存储中的状态时,就会出现问题。假设我们有一个下拉菜单打开的组件。从该下拉菜单中选择一个项目。该操作传播到ItemStore,存储发出更改,组件从存储获取新状态

我一直在慢慢地将React+Flux应用程序转换为使用Immutable.js数据结构。我使用Flux的原始、香草FB实现

我遇到的一个问题是将组件状态与从通量存储接收到的状态混合

我将所有重要的业务逻辑状态保存在商店中。但我的规则是在组件中保持与UI相关的状态。例如,商店不需要担心下拉菜单是否打开,对吗

当在组件中执行的操作改变了同一组件存储中的状态时,就会出现问题。假设我们有一个下拉菜单打开的组件。从该下拉菜单中选择一个项目。该操作传播到
ItemStore
,存储发出更改,组件从存储获取新状态

_onChange() {
  this.setState(this._getState());
}
_getState() {
  if(this.state === undefined) {
    return {
      data: Immutable.Map({
        selectedItem: ItemStore.getSelectedItem(),
        items: ItemStore.getItems(),
        menuIsOpen: false
      })
    };
  }
  return {
    data: this.state.data.merge(Immutable.Map({
      selectedItem: ItemStore.getSelectedItem(),
      items: ItemStore.getItems(),
      menuIsOpen: this.state.data.get("menuIsOpen")
    }))
  };
}
同时,在组件中,单击下拉菜单项会发出一个老式的
onClick
事件。我有一个
\u handleClick
函数,它使用setState关闭下拉菜单(本地状态)

问题是
\u handleClick
\u getState
之后很快就被调用,以至于它没有
此.state.data
的更新副本。因此,在组件的
render
方法中,
this.state.data.get(“selectedItem”)
仍然显示先前选择的项

当我使用POJO执行此操作时,React的
setState
似乎可以正确地批处理所有内容,因此它从来都不是问题。但我不想让状态不是不可变的.Map的一部分,因为我想利用“纯”的
render
ing。然而,我不想在我的商店中引入UI状态,因为我觉得这样会很快变得一团糟

我有办法解决这个问题吗还是将本地不可变映射状态和不可变映射存储状态合并到单个组件中只是一种不好的做法?


相关:我不喜欢样板
if(this.state===undefined)
逻辑,在我的
\u getState
方法中设置初始本地
menuIsOpen
状态。这可能是我试图做一些不正确的事情的迹象。

您可以通过回调将原子更新排队

\u onChange(){
this.setState(state=>this.u getState(state));
}
_getState(州){
如果(状态===未定义){
返回{
数据:Immutable.Map({
selectedItem:ItemStore.getSelectedItem(),
items:ItemStore.getItems(),
menuIsOpen:错误
})
};
}
返回{
数据:state.data.merge(Immutable.Map({
selectedItem:ItemStore.getSelectedItem(),
items:ItemStore.getItems(),
menuIsOpen:state.data.get(“menuIsOpen”)
}))
};
}

关于您的相关点,您可能想看一看。

为什么在您单击时会发生两个单独的操作(启动存储操作,关闭菜单)?相反,您可以说,当他们单击一个菜单项时,我们需要关闭该菜单项,并提醒存储区新值

_handleClick(event) {
  event.preventDefault();
  this.setState({
    data: this.state.data.set("menuIsOpen", false)
  }, function() {
    alertTheSelectionChange(selectedItem)
  });
}

将函数传递给
setState
是最终的解决方案;我完全不知道那件事。另外,re:
getInitialState
:因为我的组件使用ES6类,所以该方法不存在。由于我的组件类继承自
ImmutableFluxComponent
类,因此我在父级的
构造函数中设置初始状态。但是现在我正在使用带有
状态
参数的
\u getState
,我可以只传入一个空的不可变.Map来初始化state.data,而不使用
if
语句。解决了两个问题。非常感谢。谢谢,这也行得通——我也不知道第二个回调参数到
setState
。但是在我的例子中,将函数传递给
setState
稍微干净一些。
_handleClick(event) {
  event.preventDefault();
  this.setState({
    data: this.state.data.set("menuIsOpen", false)
  }, function() {
    alertTheSelectionChange(selectedItem)
  });
}