【问题标题】:react-redux state is always same and not chaingingreact-redux 状态始终相同且不变
【发布时间】:2021-02-19 06:25:38
【问题描述】:

我正在使用 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;
}

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

当您看到状态时,它变得相同而不是更新

【问题讨论】:

  • 在 ADD_ARTICLES 中,您返回相同的静态对象,在 UPDATE_ARTICLE 中,您正在变异,here 是您应该这样做的方式。
  • 你是对的,但我将添加文章案例返回到 {...state,articles : [...state.articles,...action.payload]} 但注意到发生了

标签: reactjs redux state dispatch


【解决方案1】:

Redux 工具包

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

以下是使用 createReducer 实用程序的减速器的外观:

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 可以为您创建动作名称和动作创建函数!

原版还原

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

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 没有其他属性要复制。但是,如果您以后想添加其他属性,最好还是包含它。

【讨论】:

  • 感谢您的回答我在 2 天前解决了这个问题。一起调用 probs 和 setState 函数会导致对 redux 的这种误解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
  • 2016-09-22
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
  • 1970-01-01
相关资源
最近更新 更多