【问题标题】:Redux: What is the best way to toggle a boolean value in a normalized state tree?Redux:在标准化状态树中切换布尔值的最佳方法是什么?
【发布时间】:2018-12-30 02:47:50
【问题描述】:

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

为了让用户过滤项目,我在 Normalizr 架构中丰富了服务器响应:

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;
    }
  }
);

对应的reducer现在看起来像这样:

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

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

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>
    );
  }
}

我现在要实现&lt;Switch /&gt; component's onValueChange() 函数,这就是我的问题所在:

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

我想出了两个解决方案,我将在下面进行描述。如果您认为其中任何一个是好的,请告诉我。如果不是,我很想得到关于我可以做得更好的建议:)

方案一:扩展reducer:

我对这个问题的第一个解决方案是扩展 reducer 以监听 TOGGLE_ITEM 动作。这看起来像这样:

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;
  }
};

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

解决方案 2:丰富将项目传递给 SwitchList 的选择器:

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

const toggleItem = (item, stateKey) => ({
  type: TOGGLE_ITEM,
  payload: {entities: { [stateKey]: item } }
})

如果您对 Redux 有丰富的经验,我很乐意阅读答案,最好是固执己见。另外,如果您认为我在 normalizr 中丰富数据的方法不好,您可以提出更好的方法,请告诉我!非常感谢您的任何建议!

【问题讨论】:

    标签: redux react-redux normalizr redux-actions


    【解决方案1】:

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

    我创建了一个数组来保存切换项的 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
    );
    

    【讨论】:

      猜你喜欢
      • 2010-10-18
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      • 2022-01-11
      • 1970-01-01
      • 2020-03-27
      • 2016-11-24
      • 1970-01-01
      相关资源
      最近更新 更多