首页 文章

为React可重用组件设计Redux操作和Reducer

提问于
浏览
19

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

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

但是Redux reducers返回一个新状态并将其保存在商店中,并将reducer的名称作为键,并且禁止在同一页面中使用相同的actions和reducers但在保持不同状态的情况下在同一类型中具有多个相同类型的组件 .

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

  • 为我使用的每个组件创建不同的操作和缩减器,甚至认为组件及其功能是相同的 . 这个解决方案似乎不是一个好的解决方案,因为会有很多冗余代码 .

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

我推出了第二个选项 .

CheckBox组件的Actions文件:

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操作和Reducer绑定在一起是错误的吗?

2 回答

  • 10

    不要根据使用该状态的组件描述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} />
         }
    }
    
  • 4

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

相关问题