19

我正在使用 Redux 和 React 开发一个大型应用程序,我决定制作一些可重用的组件,例如自定义复选框和单选按钮。

由于我想将此信息存储到 Redux 存储中以便能够轻松地调试应用程序的状态,并且相同的组件在任何地方都具有相同的功能,因此为每个组件创建减速器和操作似乎是个好主意。

然而,Redux reducer 返回一个新状态并将其保存在 store 中,并以 reducer 的名称作为键,这禁止在同一页面中使用相同的操作和 reducer 但保持不同状态的多个相同类型的组件。

我认为这个问题有两种解决方案:

  • 为我使用的每个组件创建不同的 action 和 reducer,即使组件和它的功能是相同的。这种解决方案似乎不是一个好的解决方案,因为会有很多冗余代码。

  • 创建具有足够参数的操作,以便能够区分 reducer 中的每个操作,并且只更改指定状态的一部分。

我选择了第二个选项。

CheckBox 组件的操作文件:

import {createAction} from 'redux-actions';

/****** Actions ******/
export const CHANGE_CHECKBOX_STATE = "CHANGE_CHECKBOX_STATE";

/****** Action creators ******/
export const changeCheckboxState = createAction(CHANGE_CHECKBOX_STATE, (block, name, state) => {
  return {
    block,
    name,
    state: {
      checked: state,
    }
  };
});

CheckBox 组件的 Reducers 文件:

import {handleActions} from 'redux-actions';

import {CHANGE_CHECKBOX_STATE} from './CheckBox.actions';

export const checkBoxComponent = handleActions({
  CHANGE_CHECKBOX_STATE: (state, action) => ({
    [action.payload.block]: {
      [action.payload.name]: action.payload.state
    }
  })
}, {});

block用来指定页面,name指定特定组件的名称(例如性别)和状态,以及具有新状态的对象。

但是这个解决方案也有一些问题:

  • 无法指定每个组件的初始状态,因为状态的键是动态的。
  • 许多嵌套状态使存储结构复杂化。
  • 按组件而不是表单聚合数据,这会使调试复杂化,并且在逻辑上是不正确的。

我没有足够的使用 Redux 和 React 的经验来想出一个更好的解决方案来解决这个问题。但在我看来,我遗漏了一些关于 React-Redux 关系的重要内容,这引发了一些问题:

  • 将这个可重用组件的状态存储到 Redux 存储中是个好主意吗?

  • 将 React 组件与 Redux 操作和减速器绑定在一起我错了吗?

4

2 回答 2

11

不要根据使用该状态的组件来描述您的 Redux reducer(您的整体应用程序状态)。以另一种方式跟踪它,以描述性方式描述您的应用程序状态,然后让您的“愚蠢”组件使用该描述性状态。

与其跟踪“与 foo 相关的表单的此复选框的状态”,不如跟踪“foo 的此布尔值”,然后让复选框使用该状态。

复选框的示例商店:

const initialState = {
    someFooItem: { isCertainType: false }
};

export function foos(state = initialState, action) {
    switch(action.type){
        case(UPDATE_FOO_VALUE):
            return {
                ...state, 
                [action.payload.id]: {
                    isCertainType: action.payload.isCertainType
                }
            }
    }
}

消费商店的示例复选框

class CheckBox extends React.Component {
    render() {
        return <input type="checkbox" checked={this.props.checked} />
    }
}

父组件

class ParentComponent extends React.Component {
     render() {
         return <CheckBox checked={this.foo.isCertainType} />
     }
}
于 2015-10-03T17:42:50.487 回答
4

这里的根本错误是你有 0 个哑组件。像复选框这样的基本控件应该是只使用道具的哑组件,它们的父级有责任为特定的复选框选择和更新适当的状态。

于 2015-08-28T14:21:27.117 回答