react-redux 状态始终相同且不链接

时间:2021-02-19 06:25:38

标签: reactjs redux state dispatch

我正在使用 redux,每次调用调度时都会调用我的 reducer 函数,但状态没有更新。并且第一个状态和下一个状态之间没有区别。

ArtclesReducer.ts

const defaultState: Articles = {
    articles: [{token: "teken", title: "text", featureImageUrl: ""}],
}

export const articlesReducer: Reducer<Articles, any> = (state = defaultState, action: ArticlesActionTypes) => {
    let nextState: Articles = {
        articles: state.articles,
    }

    switch (action.type) {
        case ADD_ARTICLES :
            let allArticles = [...state.articles, ...action.payload]
            return {
                articles: [{title: "", token: "", featureImageUrl: ""}, {
                    title: "",
                    token: "",
                    featureImageUrl: ""
                }, {title: "", token: "", featureImageUrl: ""}, {title: "", token: "", featureImageUrl: ""}]
            }
        case UPDATE_ARTICLE:
            console.log("in update article")
            for (let i = 0; i < nextState.articles.length; i++) {
                if (nextState.articles[i].token == action.payload.token) {
                    nextState.articles[i] = action.payload;
                    break;
                }
            }
            break;
        case DELETE_ARTICLE:
            console.log("in delete article")
            nextState.articles = nextState.articles.filter(value => {
                return value.token != action.payload;
            })
            break;
        default:
    }
    return nextState;
}

如图所示,我返回一个非空状态。

enter image description here

当您看到状态时,它变得相同并且不会更新

1 个答案:

答案 0 :(得分:1)

Redux 工具包

如果您不确定如何在不改变状态的情况下更新状态,您可以使用 Redux Toolkit 避免很多挫折。该工具包使您可以像更改状态一样编写代码(它处理幕后的不变性问题)。

以下是使用 createReducer 实用程序时此 reducer 的外观:

const articlesReducer = createReducer(defaultState, {
  [ADD_ARTICLES]: (state, action) => {
    // We don't return anything.  We just mutate the passed-in draft state.
    state.articles.push(action.payload);
  },
  [UPDATE_ARTICLE]: (state, action) => {
    // Find which article we are updating
    const index = state.articles.findIndex( 
      article => article.token === action.payload.token
    );
    // Replace that index with the new article from the payload
    state.articles[index] = action.payload;
  },
  [DELETE_ARTICLE]: (state, action) => {
    // We replace the articles array with a filtered version
    state.articles = state.articles.filter(
      article => article.token === action.payload
    );
  }
});

大多数人不直接使用 createReducer,因为有一个更好的实用程序 createSlice 可以为您创建动作名称和动作创建者函数!

原版 Redux

当然,您仍然可以采用“老式”方式来执行此操作。但是您需要确保永远不会改变状态的任何部分,并且每个案例都返回一个完整的状态。

nextState.articles[i] = action.payloadactually a mutation 即使 nextState 是一个副本,因为它是一个浅拷贝,所以 articles 属性指向与当前状态相同的数组。

除非您确信自己知道自己在做什么,否则我不推荐这种方法,但我想提供一个正确的版本来向您展示它是如何完成的。

export const articlesReducer: Reducer<Articles, any> = (state = defaultState, action: ArticlesActionTypes) => {
  switch (action.type) {
    case ADD_ARTICLES:
      return {
        ...state,
        articles: [...state.articles, ...action.payload]
      };
    case UPDATE_ARTICLE:
      return {
        ...state,
        articles: state.articles.map((article) =>
          article.token === action.payload.token ? action.payload : article
        )
      };
    case DELETE_ARTICLE:
      return {
        ...state,
        articles: state.articles.filter((article) => 
          article.token !== action.payload
        )
      };
    default:
      return state;
  }
};

注意:像您在 most examples 中看到的那样编写 ...state 在技术上是不必要的,因为 articles 是您所在州的唯一属性,因此 ...state 没有其他属性可以复制{1}}。但是,如果您想在将来添加其他属性,无论如何都包含它可能是个好主意。

相关问题