我目前正在使用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中丰富数据的方法不好,并且可以提出更好的方法,请告诉我!非常感谢您的任何建议!
答案 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
);