I translate component to hook code and I have difference between both.
(note that the Refresher is callback the fetchApi to refresh data)
export default class myComponent extends Component {
constructor(props) {
super(props);
this.state = { test: false };
}
componentDidMount() {
this.fetchApi();
}
fetchApi = () => {
console.log("fetchApi: " + this.state.test);
this.setState({ test: !this.state.test }, () => console.log("useEffect: " + this.state.test));
}
render() {
return <div>
<label>{"test: " + this.state.test}</label>
<Refresher refresh={this.fetchApi.bind(this)} />
</div>
}
}
On my screen, test is switching true to false and false to true at each refresh.
export default function myHook(props) {
const [test, setTest] = useState(false);
let TEST = false;
useEffect(() => fetchApi(), []);
useEffect(() => console.log("useEffect: " + test), [test]);
const fetchApi = () => {
console.log("fetchApi: test = " + test);
console.log("fetchApi: TEST = " + TEST);
setTest(!test);
TEST = !TEST;
}
return <div>
<label>{"test: " + test}</label>
<Refresher refresh={fetchApi} />
</div>
}
On my screen, test is staying on true value
On console.
Component:
fetchApi: false
useEffect: true
fetchApi: true
useEffect: false
fetchApi: false
useEffect: true
Hook:
fetchApi: test = false
fetchApi: TEST = false
useEffect: false
useEffect: true
fetchApi: test = false
fetchApi: TEST = true
fetchApi: test = false
fetchApi: TEST = false
Why my test variable is it always to false value?
2
Answers
The class components and function components with hooks are not exactly the same, but they are equivalent in most cases.
Your
test
variable is alwaysfalse
in the hook code because you are using the stale state value in thefetchApi
function. When you callsetTest
, you are not updating thetest
variable immediately, but scheduling a state update for the next render. However, thefetchApi
function still has a closure over the old test value – false.To fix this, you can use a functional update for
setTest
, which will use the latest state value.For example:
I think you have some mistake in logging.
Inside functional component you have a variable:
That variable will be created each render with value false and inside fetchApi (which is also recreated each render) variable TEST always will be false. The TEST variable update to true will not be kept as new variable is created each render. But you have following logging:
where variable TEST has different values. Imho in logging there is a mistake (typo or whatever) and test should true/false and TEST should be always false.
Codesandbox snippet of your example – https://codesandbox.io/s/test-example-lv2qks
And it seems all work as expected.