【问题标题】:Change the state of an array of checkboxes on the reducer as it changes in the UI在 UI 中更改时更改 reducer 上的复选框数组的状态
【发布时间】:2018-12-10 21:40:40
【问题描述】:

我在 React 上有类似的东西:

const CheckboxItems = (t) => [ // that t is just a global prop
  {
    checked: true,
    value: 'itemsCancelled',
    id: 'checkBoxItemsCancelled',
    labelText: t('cancellations.checkBoxItemsCancelled'),
  },
  {
    checked: true,
    value: 'requestDate',
    id: 'checkboxRequestDate',
    labelText: t('cancellations.checkboxRequestDate'),
  },
  {
    checked: true,
    value: 'status',
    id: 'checkboxStatus',
    labelText: t('cancellations.checkboxStatus'),
  },
  {
    checked: true,
    value: 'requestedBy',
    id: 'checkboxRequestedBy',
    labelText: t('cancellations.checkboxRequestedBy'),
  },
];

class TableToolbarComp extends React.Component {
  state = {
    items: CheckboxItems(),
  };

  onChange = (value, id, event) => {
    const { columnsFilterHandler } = this.props;
    this.setState(({ items }) => {
      const item = items.slice().find(i => i.id === id);
      if (item) {
        item.checked = !item.checked;
        columnsFilterHandler(id, item.value, item.checked);
        return { items };
      }
    });
  };

  render() {
    const { items } = this.state;

    return(
      <>
             {items.map(item => (
                <ToolbarOption key={item.id}>
                  <Checkbox
                    id={item.id}
                    labelText={item.labelText}
                    value={item.value}
                    checked={item.checked}
                    onChange={this.onChange}
                  />
                </ToolbarOption>
              ))}
      </>
    )
  }

export default compose(
  connect(
    ({ cancellations }) => ({
      columnId: cancellations.columnId,
      columnValue: cancellations.columnValue,
      isChecked: cancellations.isChecked,
    }),
    dispatch => ({
      columnsFilterHandler: (columnId, columnValue, isChecked) => {
        dispatch(columnsFilterAction(columnId, columnValue, isChecked));
      },
    }),
  ),
)(translate()(TableToolbarComp));

效果很好,它正在调度我以后需要使用的数据。

但是我在 Redux 部分有一个混乱,它一次改变所有复选框的状态,而不是像它应该的那样单独改变。因此,一旦我取消选中其中一个复选框,其他 3 个复选框也会得到 checked: false。我在 UI 上没有看到对 checked: false 的更改,只有我在浏览器的 Redux 控制台上看到它。

这就是我在减速器里的东西

const initialState = {
  checkboxes: [
    {
      checked: true,
      value: 'itemsCancelled',
      id: 'checkBoxItemsCancelled',
    },
    {
      checked: true,
      value: 'requestDate',
      id: 'checkboxRequestDate',
    },
    {
      checked: true,
      value: 'status',
      id: 'checkboxStatus',
    },
    {
      checked: true,
      value: 'requestedBy',
      id: 'checkboxRequestedBy',
    },
  ],
}

[ActionTypes.COLUMNS_FILTER](state, action) {
    return initialState.checkboxes.map(checkbox => {
      if (!checkbox.id === action.payload.id) {
        return checkbox;
      }
      return {
        ...checkbox,
        checked: action.payload.isChecked,
      };
    });
 }

行动:

const columnsFilterAction = (columnId, columnValue, isChecked) => ({
  type: ActionTypes.COLUMNS_FILTER,
  payload: { columnId, columnValue, isChecked },
});

所以我需要知道的是,当 Redux 在 React 上工作时,我必须做些什么来管理这些复选框的状态。正如我所看到的,当我切换复选框时,它们都达到了相同的状态。

【问题讨论】:

    标签: javascript reactjs ecmascript-6 redux


    【解决方案1】:

    你有!checkbox.id === action.payload.id 作为你的条件逻辑。由于您所有的复选框 ID 都是“真实的”,因此此 !checkbox.id 的计算结果为 false,与编写 if(false === action.payload.id) 相同。

    我怀疑你的意思是写:if(checkbox.id !== action.payload.id)

    【讨论】:

    • 我已经改变了它,但我仍然没有得到我需要的东西。你确定我的代码有问题吗?
    【解决方案2】:

    您要做的是传递要在操作中切换的复选框的id。这就是切换状态所需的全部内容。然后在 reducer 中,您要映射当前状态,只需返回与操作中传递的 id 不匹配的复选框。当id 匹配时,返回一个新选项,将当前复选框的属性传播到新对象中,并将checked 属性设置为相反。

    鉴于此操作:

    const TOGGLE_CHECKBOX = 'TOGGLE_CHECKBOX'
    function toggleCheckbox(id) {
      return {
        type: TOGGLE_CHECKBOX,
        id
      }
    }
    

    Actions - Redux - Redux 作者提供的动作和动作创建者指南。

    这个 reducer 可以完成这项工作。

    function checkboxReducer(state = [], action = {}) {
      switch(action.type) {
        case TOGGLE_CHECKBOX:
          return state.map(checkbox => {
            if (checkbox.id !== action.id) {
              return checkbox;
            }
            return {
              ...checkbox,
              checked: checkbox.isChecked ? false : true,
            }
          })
        default:
          return state;
      }
    }
    

    Reducers - Redux - 由 Redux 作者提供的 reducer 以及如何处理操作的指南。

    这是一个有效的Code Sandbox 来证明它是有效的。您可以单击复选框以查看它们按预期切换。

    【讨论】:

    • 我收到此错误 -> Uncaught TypeError: state.map is not a function
    • 确保将状态的默认形状设置为数组。 (state = [], action = {})
    • 对不起,我没有得到那部分。如果你看到我的代码,我的 reducer 顶部有一个 initialState 对象。你是这个意思吗?
    • @TheUnnamed 我制作了一个代码沙箱供您查看,以便您可以看到它的运行情况。我将它添加到我的帖子底部。
    • 好的,我已经看到了代码沙箱链接,但是在尝试使您的解决方案适应我的代码时遇到了问题。
    猜你喜欢
    • 2011-12-24
    • 2019-04-20
    • 2015-11-20
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2021-12-19
    • 2021-02-15
    • 1970-01-01
    相关资源
    最近更新 更多