调度操作时未调用redux connect mapStateToProps

Posted

技术标签:

【中文标题】调度操作时未调用redux connect mapStateToProps【英文标题】:redux connect mapStateToProps not called when action is dispatched 【发布时间】:2019-09-28 03:20:49 【问题描述】:

解决方案(更新):

我认为任何动作都会导致 react-redux-connect 调用 mapState 函数,但当动作没有改变任何东西时,情况并非如此。

我有一个 localStorage 模块,它调度动作但不改变状态,而是你将写入 localStorage。该模块具有在容器中使用的选择器,但在状态实际更改之前不会调用它们,因此 UI 只会在调度另一个会更改状态的操作后正确显示。

问题

当我将商店放在窗口(@98​​7654325@)上时,在 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;
;

app.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 ,
  ;
;

components/counter/component.js:

import React from 'react';

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

天啊..花了几个小时之后...这 3 个点救了我的命..谢谢 :-) @CodeWriter 我不知道您是否遇到与我相同的问题,但是如果该操作遇到了更改某些内容的减速器,则说明您的减速器处于变异状态,而 ...state 不是最适合您的解决方案。在我的情况下,reducers 没有改变任何东西,只是中间件写入本地存储。 我在第 3 个 Google 页面上找到了您的帖子...感谢这个简单但有效的技巧!【参考方案2】:

您的示例代码笔工作得很好,您只需要触发一个通过您的***警卫并且具有预期结构的操作,以免导致任何后续错误:

将此发布到您的代码笔的控制台中:

store.dispatch(emittedBy: "COUNTER", type: "COUNTER -> INCREASE", id: "counter1", payload: type: "INCREASE", id: ["counter1"])

【讨论】:

感谢您的回答,我认为调度 any 操作会导致 connect 调用 mapState/Dispatch 函数。当操作不会导致状态发生任何变化时,情况并非如此。问题的解决方法是here;在根 reducer 中返回 ...state

以上是关于调度操作时未调用redux connect mapStateToProps的主要内容,如果未能解决你的问题,请参考以下文章

在 redux 中在哪里调度多个操作?

在 React Redux 中调度操作之前等待多个 Axios 调用

模拟 API 调用时未填充 Redux 存储

redux connect的浅比较说明

调度操作后 Redux 状态未更新

如何使用 Redux connect 中的操作对测试组件进行快照?