Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Hook delayed useEffect firing?

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>
      )
  }


}
like image 704
Robert Templeton Avatar asked Sep 04 '19 12:09

Robert Templeton


People also ask

What is useeffect in react hooks?

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.

Why is it so hard to work with time effects in react?

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.

Why is it so hard to implement delayed callbacks in react?

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.

Why useeffect() is not available in react 18?

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.


2 Answers

    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])
like image 172
Abu Dujana Mahalail Avatar answered Oct 29 '22 23:10

Abu Dujana Mahalail


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.

like image 31
jpmarks Avatar answered Oct 29 '22 23:10

jpmarks