title: React Rerun an animation every time a string update
body: <p>I would like to create a React component which takes a string rerun an animation every time a char has changed on the string.
  But I would like to run the animation only on updated chars.</p>
  <p>I Ended up with this code, but the animation is rerun only one times on two and I can't see what is the issue.</p>
  <pre><code>interface AnimatedStringProps {
    string: string;
  }
  
  interface AnimatedStringChar {
    char: string;
    update: boolean;
  }
  
  export function AnimatedString({ string }: AnimatedStringProps) {
    const [chars, setChars] = useState&lt;AnimatedStringChar[]&gt;([]);
  
    useEffect(() =&gt; {
      const newstring = string.split('');
      if (newstring.length !== chars.length) setChars(newstring.map((char) =&gt; ({ char, update: false })));
      else {
        console.log('DBG', chars);
        for (let i = 0; i &lt; chars.length; i++) {
          if (newstring[i] !== chars[i].char) chars[i].update = true;
          else chars[i].update = false;
          chars[i].char = newstring[i];
          setChars(chars);
        }
      }
    }, [string]);
  
    const handleAnimationEnd = (index: number) =&gt; {
      console.log('Handle animation end', index);
      chars[index].update = false;
      setChars(chars);
    };
  
    return (
      &lt;div className=&quot;AnimatedString&quot;&gt;
        {chars.map(({ char, update }, index) =&gt; (
          &lt;span
            key={index}
            className={classNames('AnimatedString__Char', 'animate__animated', {
              animate__fadeIn: update,
            })}
            onAnimationEnd={() =&gt; handleAnimationEnd(index)}
          &gt;
            {char}
          &lt;/span&gt;
        ))}
      &lt;/div&gt;
    );
  }
  
  .AnimatedString__Char {
    display: inline-block;
    min-width: 1ch;
    animation-duration: 1s;
  }
  </code></pre>
  <p>And I use the component by passing it a stat updated every 5seconds</p>
  <pre><code>function UseComponent {
    const [test, setTest] = useState&lt;string&gt;('Hello 000 world');
    let count = 0;
    useEffect(() =&gt; {
      setInterval(() =&gt; {
        count++;
        setTest(`Hello ${count.toString().padStart(3, '0')} world`);
      }, 5000);
    }, []);
    return (&lt;div&gt;&lt;AnimatedString string={test} /&gt;&lt;/div&gt;)
  }
  </code></pre>