React:Redux 状态在一个效果中更新,但同一组件中的下一个效果是使用状态的先前值
React: Redux state updated in one effect but next effect in same component is using previous value of state
使用 react 16.8.2, hooks API.
Redux 初始状态:
const initialState = {
name: one,
count: 1,
}
分量:
function CompTwo(props) {
useActiveCount(setActiveCount, 2);
useEffect(() => {
// activeCount is still 1
if(activeCount === 2) {
setActiveName('two')
}
});
}
const mapStateToProps = state => ({
activeCount: state.count,
});
const mapDispatchToProps = dispatch => ({
setActiveCount: count => dispatch(updateActiveCount(count)),
setActiveName: name => dispatch(updateActiveName(name),
});
export default connect(mapStateToProps, mapDispatchToProps)(CompTwo);
useActiveCount:
const useActiveCount = function (setActiveCount, count) {
useEffect(() => {
setActiveCount(count);
})
}
在 CompTwo
中,如果我在设置活动名称 setActivePage('two')
之前设置计数 useActiveCount(setActiveCount, 2);
,我不应该在 activeCount
中获得新值 2
]道具?
它确实将 activeCount
设置为 2,当我在 dev-tool 控制台中检查 redux logger 中的状态值时,但是在 CompTwo
的 useEffect
代码中,我仍然变老了activeCount
的值即 1
.
为什么会这样?
您需要将 activeCount 传递给 useEffect
挂钩,否则它不会在操作完全完成后重新触发挂钩。
function CompTwo({ activeCount, setActiveCount, setActiveName }) {
useActiveCount(setActiveCount, 2);
useEffect(() => {
if(activeCount === 2) {
setActiveName('two');
}
}, [activeCount]);
}
可运行示例:
// Custom hook
const useActiveCount = (setActiveCount, count) => {
React.useEffect(
() => {
setActiveCount(count);
}, [count]
);
};
// Redux types
const SET_ACTIVE_COUNT = "SET_ACTIVE_COUNT";
const SET_ACTIVE_NAME = "SET_ACTIVE_NAME";
// Redux actions
const updateActiveCount = count => ({
type: SET_ACTIVE_COUNT,
count,
});
const updateActiveName = name => ({
type: SET_ACTIVE_NAME,
name,
});
// Redux Reducer
const reducer = (state = { count: 0 }, action) => {
switch (action.type) {
case SET_ACTIVE_COUNT:
return {
...state,
count: action.count
};
case SET_ACTIVE_NAME:
return {
...state,
name: action.name
};
default:
return state;
}
};
const store = Redux.createStore(reducer);
// Comp 2
function CompTwo({ activeCount, activeName, setActiveCount, setActiveName }) {
useActiveCount(setActiveCount, 2);
React.useEffect(() => {
console.log(activeCount);
if (activeCount === 2) {
console.log('hit');
setActiveName('Two');
}
}, [activeCount]);
return (
<React.Fragment>
<h5>Count: {activeCount}</h5>
<h5>Name: {activeName}</h5>
</React.Fragment>
);
}
const mapStateToProps = state => ({
activeCount: state.count,
activeName: state.name,
});
const mapDispatchToProps = dispatch => ({
setActiveCount: count => dispatch(updateActiveCount(count)),
setActiveName: name => dispatch(updateActiveName(name)),
});
const Comp = ReactRedux.connect(
mapStateToProps,
mapDispatchToProps
)(CompTwo);
// App
const App = () => (
<ReactRedux.Provider store={store}>
<Comp />
</ReactRedux.Provider>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.1/react-redux.min.js"></script>
<div id="root"></div>
使用 react 16.8.2, hooks API.
Redux 初始状态:
const initialState = {
name: one,
count: 1,
}
分量:
function CompTwo(props) {
useActiveCount(setActiveCount, 2);
useEffect(() => {
// activeCount is still 1
if(activeCount === 2) {
setActiveName('two')
}
});
}
const mapStateToProps = state => ({
activeCount: state.count,
});
const mapDispatchToProps = dispatch => ({
setActiveCount: count => dispatch(updateActiveCount(count)),
setActiveName: name => dispatch(updateActiveName(name),
});
export default connect(mapStateToProps, mapDispatchToProps)(CompTwo);
useActiveCount:
const useActiveCount = function (setActiveCount, count) {
useEffect(() => {
setActiveCount(count);
})
}
在 CompTwo
中,如果我在设置活动名称 setActivePage('two')
之前设置计数 useActiveCount(setActiveCount, 2);
,我不应该在 activeCount
中获得新值 2
]道具?
它确实将 activeCount
设置为 2,当我在 dev-tool 控制台中检查 redux logger 中的状态值时,但是在 CompTwo
的 useEffect
代码中,我仍然变老了activeCount
的值即 1
.
为什么会这样?
您需要将 activeCount 传递给 useEffect
挂钩,否则它不会在操作完全完成后重新触发挂钩。
function CompTwo({ activeCount, setActiveCount, setActiveName }) {
useActiveCount(setActiveCount, 2);
useEffect(() => {
if(activeCount === 2) {
setActiveName('two');
}
}, [activeCount]);
}
可运行示例:
// Custom hook
const useActiveCount = (setActiveCount, count) => {
React.useEffect(
() => {
setActiveCount(count);
}, [count]
);
};
// Redux types
const SET_ACTIVE_COUNT = "SET_ACTIVE_COUNT";
const SET_ACTIVE_NAME = "SET_ACTIVE_NAME";
// Redux actions
const updateActiveCount = count => ({
type: SET_ACTIVE_COUNT,
count,
});
const updateActiveName = name => ({
type: SET_ACTIVE_NAME,
name,
});
// Redux Reducer
const reducer = (state = { count: 0 }, action) => {
switch (action.type) {
case SET_ACTIVE_COUNT:
return {
...state,
count: action.count
};
case SET_ACTIVE_NAME:
return {
...state,
name: action.name
};
default:
return state;
}
};
const store = Redux.createStore(reducer);
// Comp 2
function CompTwo({ activeCount, activeName, setActiveCount, setActiveName }) {
useActiveCount(setActiveCount, 2);
React.useEffect(() => {
console.log(activeCount);
if (activeCount === 2) {
console.log('hit');
setActiveName('Two');
}
}, [activeCount]);
return (
<React.Fragment>
<h5>Count: {activeCount}</h5>
<h5>Name: {activeName}</h5>
</React.Fragment>
);
}
const mapStateToProps = state => ({
activeCount: state.count,
activeName: state.name,
});
const mapDispatchToProps = dispatch => ({
setActiveCount: count => dispatch(updateActiveCount(count)),
setActiveName: name => dispatch(updateActiveName(name)),
});
const Comp = ReactRedux.connect(
mapStateToProps,
mapDispatchToProps
)(CompTwo);
// App
const App = () => (
<ReactRedux.Provider store={store}>
<Comp />
</ReactRedux.Provider>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.1/react-redux.min.js"></script>
<div id="root"></div>