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}]
}
AIM
现在,我需要为Feed中的每个项目使用属性feed
更新Redux State中的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
属性的,但是源的重新呈现从未发生。麻烦的解决方法
在feed
操作中将t
分配给新变量UPDATE_FEED
正确地突变,然后发送分派调用。
但是我不确定这是否是最有效的方法。
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看起来像这样。非常简单,仅使用新值进行更新,所有情况均由单一切换方法处理。
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;
答案 0 :(得分:0)
在UPDATE_FEED操作中将提要分配给新变量t正确变异
这只是意味着,您的化简器没有创建新的状态对象。它只是改变了状态。
它使用===
来检查状态树中的状态更新。
...action.payload
可以处理供稿对象和嵌套元素的引用,因为它处于新状态。因此,没有状态更新。
像这样更改cons.UPDATE_FEED
。
state = {
...state,
...action.payload.feed,
}