调度操作时未调用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 只会在调度另一个会更改状态的操作后正确显示。
问题
当我将商店放在窗口(@987654325@)上时,在 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的主要内容,如果未能解决你的问题,请参考以下文章