javascript - redux connect mapStateToProps 在调度 Action 时不调用

标签 javascript reactjs redux react-redux

Solution(updated):

我认为任何 操作都会导致 react-redux-connect 调用 mapState 函数,但是当操作没有改变任何东西时,情况就不是这样了。

我有一个 localStorage 模块,它可以分派(dispatch)操作但不更改状态,而是将写入 localStorage。该模块具有在容器中使用的选择器,但在状态实际发生更改之前不会调用它们,因此只有在分派(dispatch)另一个会更改状态的操作后,UI 才会正确显示。

Problem

当我将商店放在窗口 (window.store=store) 上时,在 mapStateToProps 中添加一个 console.log,然后在控制台中我调度一个操作:store.dispatch( {type:'some action'}) 然后 mapStateToProps 的 console.log 不显示。

我记住了结果,但是 mapStateToProps 应该被称为 see here

完整代码是 here和运行示例 here (您可以点击屏幕右下角的“控制台”链接打开控制台)。

package.json

store.js:

import { createStore } from 'redux';
export default (initialState, reducer) => {
  const store = createStore(
    reducer,
    initialState,
    window.__REDUX_DEVTOOLS_EXTENSION__ &&
      window.__REDUX_DEVTOOLS_EXTENSION__()
  );
  window.store = store;
  return store;
};

应用程序.js

import React from 'react';
import { connect } from 'react-redux';
import './App.css';
import createStore from './store';
import { Provider } from 'react-redux';
import initCounter from './components/Counter';
import {
  createWrapper,
  memoize,
} from './components/@common';
const COUNTER = 'COUNTER';
const selectCounterState = state => state.myCounter;
const counter = initCounter({
  actionWrapper: createWrapper(COUNTER, 'counter1'),
  selectors: { myState: selectCounterState },
  connect,
  memoize,
});
const initialState = {
  myCounter: counter.initialState,
};
const reducer = (state = initialState, action) => {
  if (action.emittedBy === COUNTER) {
    return {
      ...state,
      myCounter: counter.reducer(
        selectCounterState(state),
        action.payload
      ),
    };
  }
  return state;
};
const store = createStore(initialState, reducer);
const Counter = counter.container;
const App = () => (
  <Provider store={store}>
    <Counter id="counter1" parentId={[]} />
  </Provider>
);

export default App;

组件/计数器/索引:

import component from './component';
const INCREASE = 'INCREASE';
const reducer = (state, action) => {
  if (action.type === INCREASE) {
    return { ...state, count: state.count + 1 };
  }
  return state;
};
const makeState = memoize =>
  memoize((id, parentId, { count }) => ({
    id: parentId.concat(id),
    parentId,
    count,
  }));
const mapStateToProps = ({ myState }, memoize) => () => {
  const newState = makeState(memoize);
  return (state, ownProps) =>
    console.log('in map state to props', new Date()) ||
    newState(
      ownProps.id,
      ownProps.parentId,
      myState(state)
    );
};

export default ({
  actionWrapper,
  selectors,
  connect,
  memoize,
}) => {
  const actions = {
    increase: ({ id }) =>
      actionWrapper({
        type: INCREASE,
        id,
      }),
  };
  const container = connect(
    mapStateToProps(selectors, memoize),
    actions
  )(component);
  return {
    container,
    reducer,
    initialState: { count: 0 },
  };
};

组件/计数器/component.js:

import React from 'react';

export default props => (
  <div>
    <button onClick={() => props.increase(props)}>
      add
    </button>
    {props.count}
  </div>
);

最佳答案

这个问题是因为我有一个 localStorage 模块,它执行调度操作但没有改变状态,而是写入 localStorage。

该模块具有选择器,可以获取正确的数据,容器将使用它们来构建正确的状态,但由于分派(dispatch)的操作没有改变 redux 存储中的状态,react-redux 将跳过调用我的 mapState 函数(可能是内存提供者中的状态)。

解决方案是让根 reducer 返回一个新的状态引用 {...state} 这样任何操作都会导致调用 mapState 函数。

关于javascript - redux connect mapStateToProps 在调度 Action 时不调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56073812/

相关文章:

javascript - 使用 OneSignal 设置无 Access-Control-Allow-Origin

javascript - 有没有办法只获取未命名的参数?

javascript - 在 jQuery 中移动 DOM 元素(图层 slider )

reactjs - react redux,thunk 完成的事件过早发生

javascript - 如何在不突变的情况下更改具有相同值的对象的键值,同时在 javascript 中保持未更改键的引用相同?

javascript - 如何确定插入的(可能是恶意的)JavaScript 代码来自何处

reactjs - 未捕获的 TypeError : _materialUi. Styles.ThemeManager 不是函数

javascript - React Container - 从任一 reducer 访问状态

javascript - 向 SWR 发出请求时出现 typescript 问题

javascript - 单击事件不正确地更改同一类型的所有 React 组件