And what about this?
useEffect(() => {
if (val) {
// do stuff
}
}, [val]);
Answer from Max on Stack Overflowreactjs - useState with boolean value in react - Stack Overflow
javascript - React useState setter is not working on a boolean value - Stack Overflow
javascript - How to check if state default boolean false is changing to true with React Hook useEffect - Stack Overflow
reactjs - How do we check the boolean value in useEffect in react hooks? - Stack Overflow
Can’t we just use the prop value directly instead of wrapping it in a useEffect?
Say,
Component = ({bool}) => {
If (bool) playSound()
return … }
Versus:
…
UseEffect(() => if(bool) playSound(), [bool])
…
These two cases have same behavior.
Update: It’s better to use useEffect, which only fires the side effect when the dependency changes when a component re-renders. It guards against incorrectly triggering the side effect if the dependency did not change value upon component re-render.
setIsLoading is an async function and you cannot get the state value immediately after update.
setState actions are asynchronous and are batched for performance gains. setState() does not immediately mutate this. Thus the setState calls are asynchronous as well as batched for better UI experience and performance. This applies on both
functional/Classcomponents.
From React documentation
React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state. You could read more about this here
If you want to get the updated state value then use useEffect hook with dependency array. React will execute this hook after each state update.
const {useEffect, useState } = React;
const App = (props) => {
const [isLoading, setIsLoading] = useState(false)
const buttonHandler = () => {
setIsLoading(current => !current)
}
useEffect( () => {
console.log(isLoading);
}, [isLoading]);
return (
<div>
<button onClick={buttonHandler} type="button">
Change
</button>
{isLoading? "Loading...": null}
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root">
loading.....
</div>
This is the expected behavior. You may want to use useEffect to access the latest value.
Here is a thread discussing the same issue: useState set method not reflecting change immediately
Hope this helps!
You can add another useEffect which watches this change, useEffect takes a second argument which is dependency array and the effect gets called if any of the dependency array value changes .
In this case since you need to make a decision based on the nomStatus, you can add it as a dependency to your useEffect
useEffect(() => {
if (nomStatus) {
setShowCalender(true);
}
}, [nomStatus]);
You can't since React state updates are asynchronously processed, the nomStatus state update won't be available until the next render cycle. Use the res.data[0].status value to set the showCalendar state.
const [nomStatus, setNomStatus] = useState(false);
useEffect(() => {
const fetchData = async () => {
const email = localStorage.getItem("loginEmail");
try {
const res = await Axios.get(
"http://localhost:8000/service/activeStatus",
{email}
);
setNomStatus(res.data[0].status);
console.log("Get status data :" + res.data[0].status);
if (res.data[0].status){
setShowCalender(true);
}
} catch (e) {
console.log(e);
}
};
fetchData();
}, []);
Or you can use a second useEffect hook with a dependency on nomStatus state update to set the showCalendar state.
useEffect(() => {
const fetchData = async () => {
const email = localStorage.getItem("loginEmail");
try {
const res = await Axios.get(
"http://localhost:8000/service/activeStatus",
{email}
);
setNomStatus(res.data[0].status);
console.log("Get status data :" + res.data[0].status);
} catch (e) {
console.log(e);
}
};
fetchData();
}, []);
useEffect(() => {
if (nomStatus){
setShowCalender(true);
}
}, [nomStatus]);
The dependency array to useEffect is meant to inform useEffect to run when there is a change in value. So whether you pass isModalOpen or !isModalOpen, its one and the same thing as it just checks whether the value changed i.e false to true or true to false.
The way to conditionally execute something is to aadd a condition in the callback function
useEffect(()=>{
if(!isModalOpen) {
// write your code here
}
},[isModalOpen]);
However, if at some point you want to access the old and new value both in useEffect, you can implement a usePrevious hook as mentioned in the React Hook FAQs
you should write like this not your sample because every time you write a state in dependencies
useEffect(() => {
if(!isModalOpen){
// your statement
}
},[isModalOpen]);
array useEffect triggers when it changes