Home > Software design >  How to display text by letters in React with useState?
How to display text by letters in React with useState?

Time:01-12

I want to create a text where's another letter is added to the last one, like in an old computer. But the letters keeps replacing one another instead of adding to one another:

const App = () => {
  const [text, setText] = React.useState(``);
  React.useEffect(() => {
    [`x`,`y`].forEach((letter, index) => {
      setTimeout(()=> {

         // old: setText(text => text   letter) 
         setText(text => text   letter) // new: printing each letter twice

      }, 500 * index)
    })
  }, [])
  return (text)
}

ReactDOM.createRoot(document.getElementById(`root`))
  .render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>

What's the way to fix it?

Thanks!

CodePudding user response:

This is because of StrictMode. Using useEffect dont forget the cleanup function. In this case you need to cleanup timeouts or they will stack up when the component re-render and will survive of an unmount:

React.useEffect(() => {
  let ids = [];
  
  ['x', 'y'].forEach((letter, index) => {
    const id = setTimeout(() => {
      setText(text => text   letter);
    }, 500 * index);
    
    ids.push(id);
  });
  
  // cleanup !
  return () => { ids.forEach((id) => clearTimeout(id)); };
 }, [])

CodePudding user response:

your big mistake is that you didn't work on previous value of state, you make an update on your state value in every render not the previous value of state I belive your mistake will be solved by using a callback in the setText() :

setTimeout(()=> {
      setText((prev)=>prev letter)
    }, 500 * index)
  • Related