Redux:在规范化状态树中切换布尔值的最佳方法是什么?

时间:2018-07-22 13:04:29

标签: redux react-redux normalizr redux-actions

我目前正在使用React Native开发一个应用程序。该应用程序的状态非常复杂,但是由于Redux和Normalizr的原因可以管理。现在,我必须为用户实现一项功能,以过滤项目。

为了使用户能够过滤项目,我在Normalizr模式中丰富了服务器响应:

attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465

相应的减速器现在看起来像这样:

export const subCategorySchema = new schema.Entity(
  "subCategories",
  {},
  {
    idAttribute: "uuid",
    processStrategy: entity => {
      const newEntity = Object.assign({}, { name: entity.name, uuid: entity.uuid, chosen: false });
      return newEntity;
    }
  }
);

这些子类别现在使用此SwitchListItem组件显示在UI中,该组件通过选择器获取其项:

const initialState = {};
const subCategoriesReducer = (state = initialState, action) => {
  if (action.payload && action.payload.entities) {
    return {
      ...state,
      ...action.payload.entities.subCategories
    };
  } else {
    return state;
  }
};

我现在要实现<Switch /> component's onValueChange()函数,这是我提出问题的地方:

在标准化状态树中切换布尔值的最佳方法是什么?

我提出了两种解决方案,下面将对其进行描述。如果您认为其中任何一项都不错,请告诉我。如果不是这样,我很乐意就我可以做的更好的事情寻求建议:)

解决方案1:扩展减速器:

我对这个问题的第一个解决方案是扩展reducer来监听import React, { Component } from "react"; import { Switch, Text, View } from "react-native"; import PropTypes from "prop-types"; import styles, { onColor } from "./styles"; export default class SwitchListItem extends Component { static propTypes = { item: PropTypes.object }; render() { const { name, chosen } = this.props.item; return ( <View style={styles.container}> <Text style={styles.switchListText}>{name}</Text> <Switch style={styles.switch} value={chosen} onTintColor={onColor} /> </View> ); } } 动作。看起来像这样:

TOGGLE_ITEM

这是我的首选解决方案,因为它不需要很多代码。

解决方案2:丰富将项目传递到const subCategoriesReducer = (state = initialState, action) => { switch (action.type) { case TOGGLE_ITEM: if (action.payload.item.uuid in state) return { ...state, ...action.payload.item }; } if (action.payload && action.payload.entities) { return { ...state, ...action.payload.entities.subCategories }; } else { return state; } }; 的选择器:

另一种解决方案是使用带有状态键的选择器来丰富对象,同时将它们传递到列表中。然后,我可以创建一个使用此键来更新状态的操作,如下所示:

SwitchList

如果您对Redux有丰富的经验,我很想读一个答案,最好是自以为是。另外,如果您认为我在normalizr中丰富数据的方法不好,并且可以提出更好的方法,请告诉我!非常感谢您的任何建议!

1 个答案:

答案 0 :(得分:0)

我用完全不同的方式做到了。

我创建了一个数组,其中包含切换项的uuid。因此,我只需要查看该项目是否在切换数组中即可。

就像这样:

const initialState = {};

export const byId = (state = initialState, action) => {
  if (action.payload && action.payload.entities && action.payload.entities.itemClassifications) {
    return {
      ...state,
      ...action.payload.entities.itemClassifications
    };
  } else {
    return state;
  }
};

export const chosen = (state = [], action) => {
  if (action.type === TOGGLE_ITEM && action.meta === ITEM_CLASSIFICATION) {
    if (state.includes(action.payload.uuid)) {
      return state.filter(uuid => uuid !== action.payload.uuid);
    } else {
      return [...state, action.payload.uuid];
    }
  } else {
    return state;
  }
};

const itemClassificationsReducer = combineReducers({
  byId,
  chosen
});

export default itemClassificationsReducer;

export const getAllItemClassificationsSelector = state =>
  Object.values(state.itemClassifications.byId);
export const getAllItemClassificationsNormalizedSelector = state => state.itemClassifications.byId;
export const getChosenItemClassificationsSelector = state => state.itemClassifications.chosen;

export const enrichAllItemClassificationsSelector = createSelector(
  getAllItemClassificationsSelector,
  itemClassifications =>
    itemClassifications.map(val => ({ ...val, stateKey: ITEM_CLASSIFICATION }))
);

export const getItemClassificationsFilterActiveSelector = createSelector(
  getChosenItemClassificationsSelector,
  itemClassifications => itemClassifications.length > 0
);