[英]redux connect mapStateToProps not called when action is dispatched
解决方案(更新):
我以为任何动作都会导致react-redux-connect调用mapState函数,但是当一个动作什么都没有改变时,事实并非如此。
我有一个localStorage模块,该模块可以调度操作,但不更改状态,相反,您会写入localStorage。 该模块具有在容器中使用的选择器,但是直到状态实际更改时它们才被调用,因此,只有在分派了另一个更改状态的操作之后,UI才能正确显示。
问题
当我将商店放在窗口( window.store=store
)上时,在mapStateToProps中添加console.log,然后在控制台中分派一个动作: store.dispatch({type:'some action'})
然后是控制台。 mapStateToProps的日志不显示。
我确实记住了结果,但是应该调用mapStateToProps, 请参见此处
完整的代码在这里 ,运行示例在这里 (您可以单击屏幕右下角的“控制台”链接打开控制台)。
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 },
};
};
组件/计数器/ component.js:
import React from 'react';
export default props => (
<div>
<button onClick={() => props.increase(props)}>
add
</button>
{props.count}
</div>
);
您的示例代码笔工作得很好,您只需触发一个超出顶级警卫并且具有预期结构的操作即可,以免引起任何后续错误:
将其发布到您的Codepen控制台中:
store.dispatch({emittedBy: "COUNTER", type: "COUNTER -> INCREASE", id: "counter1", payload: {type: "INCREASE", id: ["counter1"]}})
造成此问题的原因是,我有一个localStorage模块,该模块执行调度操作,但未更改状态,而是将其写入localStorage。
该模块具有选择器,这些选择器将获取正确的数据,并且容器将使用它们来构建正确的状态,但是由于分派的操作并未更改redux存储中的状态,因此react-redux会跳过调用我的mapState函数(可能在Provider中记住状态) )。
解决方案是让根缩减器返回新的状态引用{...state}
以便任何操作都会导致mapState函数被调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.