Home > database >  I update state inside useEffect and expect webpage to rerender on every state update
I update state inside useEffect and expect webpage to rerender on every state update

Time:01-31

I update state inside useEffect and expect webpage to rerender on every state update but it seems like it only updates once - the last value from for loop. And despite me setting timeout the update and rerender happens instantly. What am I doing wrong?

const [definition, setDefinition] = useState('')

    useEffect(() => {
        if (startAnimationFinished) return
        if (!pathIsActive) return

        let newDef
        for (let i = 0; i < 150; i  ) {
            newDef = `M ${i} ${i} L ${i} ${i}`
            setTimeout(() => {
                setDefinition(newDef)
            }, 1000)
        }

        console.log(newDef);

        startAnimationFinished = true
    }, [pathIsActive])

    return (
        <>
            <svg
                className={'path'   (pathIsActive ? ' active' : '')}
                xmlns="http://www.w3.org/2000/svg"
                style={{ border: '1px solid blue' }}
                viewBox={`${-width / 4} ${-width / 4} ${width} ${width}`}
                {...props}
            >
                <path fill='none' stroke="white" width='1'
                    style={{ filter: "drop-shadow(0px 0px 5px white)" }}
                    d={definition}
                />
            </svg>
        </>

CodePudding user response:

  1. React state updates are batched, meaning multiple subsequent updates are going to trigger only one re-render
  2. You are effectively scheduling all setTimeouts to run at the same time

If you want to update the state in 1 second intervals you can do something like this:

const updateEverySecond = async () => {
  let i = 0;

  while (i   < 150) {
     const newDef = `M ${i} ${i} L ${i} ${i}`;

     setDefinition(newDef);

     await new Promise(resolve => setTimeout(resolve, 1000));
  }
}

useEffect(() => {
  updateEverySecond();
}, []);

CodePudding user response:

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.

consider updating multiple hooks in your useEffect, this will not be good behavior if the component will be rendered for every update. so once useEffect ends the component re render.

here if you want to store all the values without loosing any, because here you are overwritting the value of definition in every itteration you can declare definition as array

const [definition, setDefinition] = useState([]);

then update it like this :

let newDef = [];

for (let i = 0; i < 150; i  ) {
  newDef.push(`M ${i} ${i} L ${i} ${i}`)
 }
  setDefinition(newDef)

now you have the list of definitions you can display them as you want

  • Related