【问题标题】:React-Redux mapStateToProps doesn't update componentReact-Redux mapStateToProps 不更新组件
【发布时间】:2021-10-23 09:46:31
【问题描述】:

所以我简化了我的代码,但基本上我有一个直截了当的 redux 商店:

/* store.js */

import { createStore } from 'redux';

const reducer = (state = {}, action) => {
  if (action.type === 'action') state.data = data;
  return state;
}

const store = createStore(reducer);

store.subscribe(() => {
  console.log(store.getState()); // returns the right state, updates properly
});

export default store;

从服务器拉取数据并将其分派到存储的加载器:

/* Loader.js */

class Loader {
  dispatch (allDocuments) {
    store.dispatch({
      type: 'action',
      data: data
    });
  }

  async fetchData () {
    try {
      const allDocuments = await ajaxCall('GET', '/fetchData');
      this.dispatch(allDocuments);
      return allDocuments;
    } catch (e) {
      console.error(e);
    }
  }
}

export default Loader;

然后这是我的 App.js 文件,我每 5 秒触发一次 Loader fetch 方法并将存储状态映射到 React 组件:

/* App.js */

import Loader from './Loader';
const loader = new Loader();

setInterval(async () => {
  await loader.fetchData();
}, 5000);

const App = ({
  data
}) => {
  console.log(data); //doesn't update

  return (
    <div>
      <p>{data}</p>
    </div>
  )
};

const mapStateToProps = state => ({data: state.data,})

export default connect(mapStateToProps)(App);

所以这里的问题是组件没有更新。 Loader 正确调度,redux store 确实得到了更新,但 App 中的 data prop 仍然是一个空对象,并且不会重新触发 render 方法。

为什么mapStateToProps在store状态改变时不更新组件?

【问题讨论】:

  • App 是否包含在 redux 存储提供程序中,提供您在外部使用的相同存储?
  • 我越看这段代码,就越讨厌它。您的 setInterval 在组件之外,它永远不会停止。您的 Loader 直接访问 store 而不是使用 react-redux 绑定 (connect/useDispatch)。我认为这是一个错字,但data 中的 data 变量到底是什么?!
  • 我完全同意 Linda 的观点……这段代码所做的几乎所有事情都应该被视为 React 组件生命周期结构中的反模式。 redux store 是不是特定于 React 的大型应用程序的一部分吗?在 React 中,您几乎不会直接使用 store 对象来调度操作。
  • 对于尝试做的事情,即每 5 秒重新获取数据并将其存储在 Redux 中,我建议使用 RTK Query 的内置“轮询”功能:redux-toolkit.js.org/rtk-query/usage/polling
  • 等等,为什么 Loader 在 React 组件之外是一件坏事?让一个非反应类在没有任何 ui 的情况下从服务器更新数据然后让前端元素使用它是否没有意义?

标签: reactjs redux react-redux


【解决方案1】:

mapStateToProps 期望你不会改变状态。问题是您的减速器,它通过直接分配给state.data 来改变state 变量。

为避免改变状态,您需要在更改 data 时返回对象的新副本。像这样:

const reducer = (state = {}, action) => {
  if (action.type === 'action') {
     return {
        ...state,
        data: action.payload
     }
  return state;
}

当然,如果你只有一种类型的操作,那么 redux 就不是适合这项工作的工具。

【讨论】:

    【解决方案2】:

    您的 reducer 不会保存 action.data 有效负载。它也没有返回新的状态对象引用。

    const reducer = (state = {}, action) => {
      if (action.type === 'action') state.data = data; // <-- mutation
      return state;
    }
    

    当操作类型匹配时,您应该返回一个带有action.data 有效负载的新状态对象引用。

    const reducer = (state = {}, action) => {
      if (action.type === 'action') {
        return {
          ...state,
          data: action.data;
        };
      }
    
      return state;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-26
      • 2019-06-26
      • 2018-02-21
      • 2021-01-12
      • 2021-05-08
      • 2021-07-27
      • 1970-01-01
      • 2016-06-30
      相关资源
      最近更新 更多