来自iOS / swift编程世界,我发现访问特定状态属性的通用方法过于通用,我想就此问题发表您的看法
考虑以下Redux状态(可能已经有点嵌套了):
lights: {
room1: {
items: {
1: {
rgb: false,
isOn: false,
value: 50,
color: -1,
title: "Desk light"
},
2: {
rgb: false,
isOn: false,
value: 50,
color: -1,
title: "Groupe 2"
}
}
}
}
和以下选择器:
export const getLight = (state, roomId, itemId) =>
state.lights[roomId].items[itemId];
然后在组件中,将stateToProps与以下内容映射:
function mapStateToProps(state, ownProps) {
return {
light: getLight(state, ownProps.roomId, ownProps.itemId)
};
}
这是(最终)问题所在。
例如,我可以通过this.props.light.isOn
访问灯光的不同属性;例如,但是isOn
部分不提供任何类型的字符串检查,并且如果我修改状态,则必须更新依赖该属性的所有组件。
我当时正在考虑使用一个Light类,就像这样:
function mapStateToProps(state, ownProps) {
return {
light: Light(getLight(state, ownProps.roomId, ownProps.itemId))
};
}
在React / Redux中是一种好习惯吗?还是在这种情况下还有其他用途?
最后一件事,我还有一个通用操作updateLight
,为此我提供了要更新的密钥的字典。再次,我必须注意字典的键,以便它们与状态键完全匹配。
我看不到Light
类对我有什么帮助……除非我在另一个枚举中列出密钥,否则将导致大量重复。
谢谢!
答案 0 :(得分:0)
确保项目中的字段最简单的方法是使用redux存储中的类:
class Light {}
lights: {
room1: {
items: {
1: Light
}
}
}
这样,当您使用getLight
选择器时,您将获得一个类实例,而不是普通对象。对此类的任何更改将反映在列表中的所有项目中。
如果您想更深入地控制字段及其可能的值,则其他选项(例如TypeScript或Flow)可能更适合您。
在旁注中,您提到商店可能过于嵌套。 Redux建议normalizing you store使其工作起来更类似于关系数据库。
答案 1 :(得分:0)
我应该使用模型/类安全地访问状态对象属性吗?
在React中,您的组件可以直接使用映射状态。 为了更新状态,您可以调度将通过reducer处理的动作。
未验证代码
// Reducer.js
// Changes for the state data shape
const initialState = {
rooms: {
/*
room1: {
items: [
{
id: 0, // ID
rgb: false,
isOn: false,
value: 50,
color: -1,
title: "Desk light",
type: "Light", // additional attribute for Item
},
]
}
*/
}
};
export const rooms = (state=initialState, action) => {
switch(action.type) {
case UPDATE_ITEM:
const items = [...state.rooms[action.roomId].items];
let updateItem = items.find(item => item.id === action.itemId);
// do something with updatedItem
return {
...state.rooms,
[action.roomId]: {
items: items.map(item => (
item.id === action.itemId ? updatedItem : item
)),
}
}
default:
return state;
}
}
// YourComponent.js
function mapStateToProps = (state, ownProps) => {
const { rooms } = state;
return {
rooms,
};
}
function mapDispatchtoProps = dispatch => {
return {
updateItem: (item) => {
// dispatches UPDATE_ITEM action
// handled by reducer
dispatch(updateItem(item));
}
};
}
render() {
const { rooms, updateItem } = this.props;
return (
{ Object.values(rooms).map(room => (
<Room key={room.id}>
{ room.items.map(item => (
<Item key={item.id}
onChange={() => this.updateItem(item)}
{...item} // item props
/>
))}
</Room>
))}
);
}
connect(mapStateToProps, mapDispatchToProps)(YourComponent);