I am trying to use useEffect() in my react hook to update the state when my props change. but there is a delay and the useEffect is only firing after I click again on an element in my hook. Im fairly new to using hooks and any help would be appreciated. Thanks
function ImageOrderSelect (props) {
const [clicked, setClicked] = useState(false)
const [options, setOptions] = useState(props.options)
const [current, setCurrent] = useState(props.current)
useEffect(() => {
setCurrent(props.current)
}, [props.current])
if(!clicked){
return (
<div className="image-order-select-icon" onClick={() => setClicked(!clicked)}>
<FontAwesomeIcon size="lg" icon={faCircle} />
<p>{current}</p>
</div>
)
} else if(clicked){
return (
<div className="image-order-select">
{optionsList}
</div>
)
}
}
useEffect () React hook manages the side-effects like fetching over the network, manipulating DOM directly, starting and ending timers. While the useEffect () is, alongside with useState () (the one that manages state), is one of the most used hooks, it requires some time to familiarize and use correctly.
Working with time effects in React is hard. For example, building countdown components is incredibly easy to do wrong if the React component lifecycle is used incorrectly ( but can be easy, if you get a useTime hook !). The same difficulty goes for integrating delayed callbacks into the React lifecycle.
For example, building countdown components is incredibly easy to do wrong if the React component lifecycle is used incorrectly ( but can be easy, if you get a useTime hook !). The same difficulty goes for integrating delayed callbacks into the React lifecycle.
The reason for this is for paving the way for a feature that isn't in React yet, so as far as React 18 is concerned, there is no reason. For React Hooks in React 18, this means a useEffect () with zero dependencies will be executed twice.
useEffect(() => {
setTimeout(()=>{
setCurrent(props.current)
}, 1000)
}, [props.current])
You just need to add timeout/delay before displaying the current...
or Best approach add a callback function
useEffect(() => {
setCurrent(() => props.current)
}, [props.current])
Im not exactly sure what desired effect you are going for, but here is a little cleaned up code of yours. Maybe that will help you further.
function ImageOrderSelect ({ current, options ) { // deconstruct here to save code
const [clicked, setClicked] = useState(false);
// you dont have to keep additional state since props is a state.
useEffect(() => {
setTimeout(() => {
// do something here 1 sec after current has changed
}, 1000);
}, [current]);
useEffect(() => {
setTimeout(() => {
// do something 1 sec after clicked has changed
}, 1000);
}, [clicked]);
if(!clicked){
return (
<div className="image-order-select-icon" onClick={() => setClicked(!clicked)}>
<FontAwesomeIcon size="lg" icon={faCircle} />
<p>{current}</p>
</div>
)
} else if(clicked){
return (
<div className="image-order-select">
{optionsList}
</div>
)
}
}
In case you want an effect triggered 1sec after the last click on your image, you have to reset the timeout on every click untill it expires. This is common practice for any delayed effect on user interactions:
let timeout;
useEffect(() => {
clearTimeout(timeout);
timeout = setTimeout(() => {
// do something 1 sec after a click is done
// but dont do anything if another click happened before 1sec of the previous
// click has expired
}, 1000);
}, [clicked]);
I can definetlely help you if you could give a more detailed code example and more in depth explanation of your desired UI effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With