【问题标题】:Redux Action with For loop doesn't work as expected带有 For 循环的 Redux Action 无法按预期工作
【发布时间】: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
    }
  });
};

问题

所以我在这里面临一些问题:

  1. CHECKPOINT 1 处,提要对象在 Google Chrome 控制台中记录带有 isBookmarked 属性的变异提要,甚至在循环开始之前。
  2. 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


【解决方案1】:

在 UPDATE_FEED 操作中将 feed 分配给新变量 t 会正确地发生变异

这只是意味着,你的减速器没有创建新的状态对象。它只是改变了状态。

它使用=== 来检查状态树中的状态更新。

...action.payload 它处理与新状态相同的提要对象和嵌套元素引用。因此,没有状态更新。

像这样更改cons.UPDATE_FEED

state = {
           ...state,
           ...action.payload.feed,
         }

【讨论】:

  • 你是对的。但由于某种原因,我登录减速器的对象显示了一个已经更新的state,甚至在它更新之前就已经发生了变异的feed...
  • 你把调试器n检查了吗?请安装chrome redux开发工具。它将帮助你跟踪状态更新序列
猜你喜欢
  • 1970-01-01
  • 2018-01-26
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多