Closed six-666 closed 5 years ago
The same issue as this #15933. From official docs https://reactjs.org/docs/hooks-reference.html#useeffect:
Note
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders.
So, to get updated count you just need to use useEffect:
useEffect(() => {
// This code will be run every time count is changed
console.log(count); // or any other manipulation like HTTP request
}, [count]);
Also, read this https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies to avoid such issues.
@dmytro-lymarenko useReducer Using the above method can cause a dead cycle.
import React, { useEffect, useReducer } from 'react';
const initialState = {
count: 0
};
function reducer(state: any, action: any) {
switch (action.type) {
case 'setCount':
return {count: 999};
default:
return state;
}
}
const About = function () {
const [state, dispatch] = useReducer(reducer, initialState);
function init() {
dispatch({ type: 'setCount' })
getData();
}
function getData() {
// Why count is 0, The result I expect is 999
http('/', { count: state.count });
}
useEffect(() => {
init();
}, [state]);
return null
};
export default About;
Count is still 0 because you didn't provide correct dependencies for useEffect
Here is the working example: https://codesandbox.io/s/interesting-tereshkova-qlwv7
Besides the dependency issue, useReducer will not update value immediately so you should call getData
in another effect:
const About = function () {
const [state, dispatch] = useReducer(reducer, initialState);
function init() {
dispatch({ type: 'setCount' })
}
useEffect(() => {
init();
}, []);
useEffect(() => {
if (state.count === 0) {
return;
}
http('/', { count: state.count });
}, [state]);
return null
};
@otakustay GetData function needs to be external, how to deal with.
Make getData
receive count
as argument.
function getData(count) {
http('/', {count});
}
const About = function () {
const [state, dispatch] = useReducer(reducer, initialState);
function init() {
dispatch({ type: 'setCount' })
}
useEffect(() => {
init();
}, []);
useEffect(() => {
if (state.count === 0) {
return;
}
getData(state.count);
}, [state]);
return null
};