【发布时间】:2018-07-20 07:40:29
【问题描述】:
TLDR:奇怪的突变。通过重新分配变量来解决。但不是最有效的......
前言
我有一个名为 Feed 的组件连接到 redux
export class Feed extends Component {
bookmark = (id) => {
this.props.bookmarkItem(id).then(s=>{
this.props.updateFeed(this.props.feed, this.props.bookmarks);
}); //redux action with redux-thunk
}
render(){
//renders card items with a bookmark button on each card
//onPress button call this.bookmark(item.id)
}
}
const mapStateToProps = (state) => ({
feed: state.app.feed,
bookmarks: state.app.bookmarks
})
export default connect(mapStateToProps, { bookmarkItem, updateFeed })(Feed)
按下卡上的按钮时,会调用this.bookmark() 函数并调用this.props.bookmarkItem(id) 动作。
bookmarkItem redux 操作如下所示。
export const bookmarkItem = (item_id) => async dispatch => {
try {
let r = await axios.post(`/bookmark`); //api call
let { bookmarks } = r; //get updated bookmarked items from api
dispatch({
type: cons.UPDATE_BOOKMARKED,
payload: { bookmarked }
});
return true;
}
catch (err) {
throw new Error(err);
}
}
Redux 状态如下所示
let app = {
feed: [{id:1}, {id:2}, {id:3}, {id:4}],
bookmarks:[{id:1}, {id:2}]
}
目标
现在我要更新 Redux State 中的 feed 数组,并为提要中的每个项目使用属性 isBookmarked。
(以便我们可以显示该项目是否已加入书签)
因此,我正在调用另一个 updateFeed() redux 操作
export const updateFeed = (feed, bookmarks) => dispatch => {
console.log('checkpoint 1', feed); //CHECKPOINT 1
for (let i = 0; i < feed.length; i++) {
if (bookmarks.length == 0) {
feed[i].isBookmarked = false; //mark item as NOT bookmarked
} else {
//check all bookmarks
for (let p = 0; p < bookmarks.length; p++) {
//if bookmark exists, set item in feed as isBookmarked:true
if (bookmarks[p].id === feed[i].id)
feed[i].isBookmarked = true; //mark item as bookmarked
}
}
}
dispatch({
type: cons.UPDATE_FEED,
payload: {
feed
}
});
};
问题
所以我在这里面临一些问题:
- 在
CHECKPOINT 1处,提要对象在 Google Chrome 控制台中记录带有isBookmarked属性的变异提要,甚至在循环开始之前。 -
UPDATE_FEED操作的有效负载是带有isBookmarked属性的,但永远不会重新呈现提要。
解决办法
在UPDATE_FEED 操作中将feed 分配给新变量t 会正确地发生变异,然后在调度调用中发送。
但我不确定这是否是最有效的方法。
export const updateFeed = (feed, bookmarks) => dispatch => {
let t = JSON.parse(JSON.stringify(feed));
console.log('checkpoint 1', feed); //CHECKPOINT 1
for (let i = 0; i < t.length; i++) {
if (bookmarks.length == 0) {
t[i].isBookmarked = false; //mark item as NOT bookmarked
} else {
//check all bookmarks
for (let p = 0; p < bookmarks.length; p++) {
//if bookmark exists, set item in feed as isBookmarked:true
if (bookmarks[p].id === t[i].id)
t[i].isBookmarked = true; //mark item as isBookmarked
}
}
}
dispatch({
type: cons.UPDATE_FEED,
payload: {
feed : t //THIS WORKS CORRECTLY
}
});
};
等待 for 循环异步完成是不是更好的方法?
EXTRAS
Reducer 看起来像这样。很简单,只更新新值,所有情况都由单一的 switch 方法处理。
const initialState = {
feed: [],
bookmarks:[]
}
const app = (state = initialState, action) => {
console.log('appReducer', action, JSON.stringify(state));
switch (action.type) {
case cons.UPDATE_BOOKMARKS:
case cons.UPDATE_FEED:
{
state = {
...state,
...action.payload,
}
break;
}
}
return state;
}
export default app;
【问题讨论】:
-
能否请您添加相同的减速器
-
@RIYAJKHAN 添加了减速器。
标签: reactjs react-native redux react-redux