正在编辑Redux状态而不发送任何操作

时间:2018-02-06 17:30:50

标签: javascript reactjs redux

我有一个带有react + redux的应用程序,问题出现在编辑表单中。

问题描述

  1. 点击"编辑"编辑文件
  2. 显示编辑表单
  3. 我编辑/删除其中一个值
  4. 而不是保存(调度要保存的操作)我返回任何其他页面而不保存
  5. 然后返回此对象的 description 页面("编辑"按钮所在的位置)
  6. 结果

    文档已编辑。

    因此,从Portlets组件中,当我点击编辑按钮时,我{l} setState({isEditing: true})

    if(this.state.isEditing) {
      return (
        <div className="col-md-12">
          <div className="card">
            <div className="card-content">
              <PortletForm />
            </div>
          </div>
        </div>
      );
    

    然后我打开<PortletForm />组件,再次使用connect()访问数据:

    function mapStateToProps(state, ownProps) {
      let portlet = {};
    
      const portletId = ownProps.match.params.id;
    
      if (state.portlets.length > 0) {
        portlet = Object.assign({}, state.portlets.find(portlet => portlet._id === portletId));
      }
    
      return { portlet: portlet };
    }
    
    function mapDispatchToProps(dispatch) {
      return {
        actions: bindActionCreators(portletActions, dispatch)
      };
    }
    
    export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PortletForm));
    

    这是编辑表单中的constructor()

    constructor(props) {
        super(props);
    
        this.state = {
          portlet: this.props.portlet,
          addNewKey: [],
          addNewKeyDisabled: false,
          newKey: '',
          newValue: ''
        };
    
        ...
    }
    

    这是jsx中调用编辑功能的<input />

    <input
      type="text"
      className="form-control"
      autoFocus={index === 0}
      name={Object.keys(key)}
      value={Object.values(key)}
      onChange={this._updatePortletKey} /> 
    

    _updatePortletKey(),问题似乎正在发生:

    _updatePortletKey(event) {
        const field = event.target.name;
        let editedDoc = Object.assign({}, this.state.portlet);
        editedDoc._keys.map((elem, index) => {
          const key = Object.keys(editedDoc._keys[index]);
          if(key[0] === field) {
            return editedDoc._keys[index][field] = event.target.value;
          }
        });
        debugger;
        this.setState({ portlet: editedDoc });
      }
    

    所以我创建了一个新对象,并将其修改为状态,经过一些调试后,这就是我发现的:

    • 当我访问此功能时this.props.portlet包含原始对象
    • 在我从地图功能(放置调试器的地方)返回新密钥之后,在我编辑状态之前,this.props.portlet 包含已编辑的密钥!

    我真的不知道还有什么可以尝试,在此功能之前我没有触发任何调度或某些事情,但我也在console.log()mapStateToProps()尝试了回到未保存的文档,商店已编辑,我不明白!我还检查了父函数不包含任何可能同时工作的其他函数......什么都没有。

    感谢任何帮助。提前谢谢!

    编辑:这就是this.props.portlet的样子:

    {
        country: "AR"
        dev: true
        slug: "document-name"
        test: false
        version: 2
        _id: "5a798e53f2c5340bb08479f8"
        _keys: [
            { newKey: "new key value" }
        ]
    }
    

1 个答案:

答案 0 :(得分:3)

这就是为什么建议的处理redux的方法是ImmutableJSimmutable-helper或者那种。

否则很容易犯错误。

以下是发生的事情:

// constructor
this.state = {
  portlet: this.props.portlet,  // you put props in the state
}

// change handler
let editedDoc = Object.assign({}, this.state.portlet);
// here a new object is created, but if the value is not primitive, it is by reference.
// this means, while editedDoc and this.state.portlet are different objects, "_key"'s value is shared between these object.

这是我看到许多人制作的错误。此外,调试此类案件也很痛苦。所以请使用帮助库。

如果你坚持使用es6构建新对象,那么随着嵌套的增加,它可能会变得丑陋。

// example 1
_updatePortletKey(event) {
  const field = event.target.name;

  this.setState({
    portlet: {
      ...this.state.portlet,
      _keys: this.state.portlet._keys.reduce((agg, el) => {
        const key = Object.keys(el); 
        // btw, what are you trying to do here !! (my logic might be slightly off, as I didn't fully understood the transformation, but you get the idea, right?)
        if(key[0] === field) { 
          return [...agg, {...el, [field]: event.target.value}]
        }
        return [...agg,el]
      }, [])
    }
  })