如何让减速器不再返回新的状态?我的解决方案是否正常还是有更好的方法?
我的状态:
userList: {
id: 'xxx', // <-|- Not mutable by reducers fields, so using combineReducers for each field is frustrating.
ba: 'xxx', // <-|
fo: 'xxx', // <-|
users: [
{
id: 'yyy',
be: 'yyy',
fo: 'yyy',
photo: {
id: 'zzz',
url: 'http://image.jpg', <-- The only field, that changes by reducers.
},
},
...
],
}
我目前的减速机:
// Always returns new object.
const userListReducer = (userList, action) => {
return {
...userList,
users: usersReducer(userList, action),
}
};
// Always returns new array.
const usersReducer = (users, action) => {
return users.map(user => userReducer(user, action));
};
// Always returns new object too.
const userReducer = (user, action) => {
return {
...user,
photo: photoReducer(user.photo, action),
};
};
// The only one true reducer.
const photoReducer = (photo, action) => {
switch (action.type) {
case 'update_photo':
return {
...photo,
url: action.url,
};
default:
return photo;
}
};
1)。必要时呼叫usersReducer。不好的部分:我们需要关心其他减速器的逻辑。
const userListReducer = (userList, action) => {
switch (action.type) {
case 'update_photo':
return {
...userList,
users: usersReducer(userList, action),
};
default:
return userList;
}
};
2)。使用combineReducers。不好的部分:我们需要关心所有usersList的形状。此外,这仍然不起作用,因为usersReducer总是返回新数组。
const userListRecuer = combineReducers({
id: id => id,
ba: ba => ba,
fo: fo => fo,
users: usersReducer,
});
3)。我的解决方案使用mergeOrReturnOld和mapOrReturnOld帮助程序。
const userListReducer = (userList, action) => {
return mergeOrReturnOld(userList, {
users: usersReducer(userList, action),
});
};
const usersReducer = (users, action) => {
return mapOrReturnOld(users, user => userReducer(user, action));
};
const userReducer = (user, action) => {
return mergeOrReturnOld(user, {
photo: photoReducer(user.photo, action),
});
};
助手实施:
const mergeOrReturnOld = (obj, addition) => {
let hasChanged = false;
for (let key in addition) {
if (addition.hasOwnProperty(key)) {
if (obj[key] !== addition[key]) {
hasChanged = true;
}
}
}
if (!hasChanged) {
return obj;
} else {
return {
...obj,
...addition,
};
}
};
const mapOrReturnOld = (array, callback) => {
let hasChanged = false;
const newArray = array.map(item => {
const newItem = callback(item);
if (newItem !== item) {
hasChanged = true;
}
return newItem;
});
if (!hasChanged) {
return array;
} else {
return newArray;
}
};