我们是否将Redux用于所有状态更新?

时间:2018-03-13 02:17:16

标签: reactjs redux

背景:

我已经开始使用React构建应用程序。整个用户界面基于一个大对象调查,有几个(15-20)组件更新该对象的部分。调查对象通过单个服务器调用获取,对象保存,另一个调用服务器。每个组件中进行的所有元素更新都是为了更新大型Survey对象的一部分。

我打算使用Redux为每个元素/字段进行状态更新,因为它是清理和中央状态管理。

为了做到这一点,我需要绑定' onChange'所有元素的事件处理程序。例如,每次文本框值发生更改时,都会触发操作并且相应的缩减器会截取并更新状态。

因此,对于组件中的以下元素,

<input
  className="form-control form-control-lg"
  type="text"
  placeholder="Username"
  value={this.props.username}
  onChange={this.changeUsername} />

触发以下操作

onChangeUsername(){
  dispatch({ type: UPDATE_FIELD_AUTH, key: 'username', value }),
  ...
}

减速器更新状态......

(survey = {}, action) => {
  switch (action.type) {    
    case UPDATE_FIELD_AUTH:
      return { ...survey , [action.key]: action.value };
    default:
      return state;
}

简而言之,我们正在执行以下操作来更新单个字段的状态: 元素事件处理程序 - &gt;调度Redux动作 - &gt; Redux reducer更新字段



    Survey
        -> Name
        -> Description
        -> Section
            ->Name
            ->Number
            ->Question
                ->Name
                ->Type
                ->Option
                    ->Name
                    ->Type
                    ->Value

问题 应用程序中可能有100个这样的字段,可能会从两个不同的组件更新相同的字段。这是要遵循的模型吗?

1 个答案:

答案 0 :(得分:1)

我的直觉是,您希望将单个调度程序用于多个onChange事件

有组件:

const inputView = props => (
  <input
  type="text"
  placeholder="Username"
  value={this.props.username}
  onChange={e => { this.props.onChange('username', e.target.value) }} 
  />
);

有调度员:

const mapDispatchToProps = dispatch => ({
  onChange: (key, value) => dispatch({ 
    type: actionTypes.UPDATE_FIELD, 
    key, 
    value
  }),
});
export default connect(mapStateToProps, mapDispatchToProps)(inputView);

还有减速器:

const reducer = (state = initState, action) => {
  switch (action.type) {
    case actionTypes.UPDATE_FIELD:
      return {
        ...state,
        [action.key]: action.value,
      };
    default:
      return state;
  }
};

效率这么高吗?
绝对是的。
由于多个输入通过相同的条件,因此switch语句并不复杂。 此外,如果您有更多组件/部分,多个缩减器始终是一个选项。

根据React doc,即使setState也不会立即更新,但新道具将始终立即触发渲染功能。所以这个中央存储实现实际上比在每个组件中保持状态更好,你不必担心链接状态可能会出现异步或导致副作用。

<强>更新
嵌套状态的更新未在原始问题中显示,并且问题中的input设置与数据结构不匹配。

鉴于这样的状态。假设用户无法删除问题,则每个部分将按顺序呈现 跟踪索引很容易,因为我们不想在每个onChange事件中搜索状态。

const state = {
  Survey: {
    Name: '',
    Description: '',
    Section: [
      {
        Name: '',
        Number: 0,
        Question: [
          {
            Name: '',
            Type: '',
            Value: '1', // input value should be in this level
            Option: [ // handle input type="select"
              { value: '1', displayValue: '1' },
              { value: '2', displayValue: '2' },
            ],
          },
        ],
      },
    ],
  },
};

我们的想法是在最低级别创建一个深层副本。

const reducer = (state = initState, action) => {
  switch (action.type) {
    case actionTypes.UPDATE_FIELD:
      const survey = { ...state.Survey };
      const section = { ...survey.Section[action.sectionIdx] };
      const question = { ...section.Qustion[action.questionIdx] };
      question.Value = action.value;
      section[sectionIdx].Qustion = question;
      survey.Section = section;
      return {
        ...survey,
      };
    default:
      return state;
  }
};

其他信息:
Correct Approach: Copying All Levels of Nested Data

的官方链接