Home > Blockchain >  React, setInterval not working properly, h1 element not being updated correctly
React, setInterval not working properly, h1 element not being updated correctly

Time:05-26

I want to create a simple React app that upadates a h1 element every second with setInterval function. I have an array with strings and every second I want randomly pick a string from that array and uses that string inside h1. But my code doesn't work properly. h1 is not being updated every second but every millisecond.

import PersonalInfo from './PersonalInfo.js'
import { useState } from 'react';

function App() {
  const myPersonalInfo = ['books', 'music', 'code']; 
  const [state, changeState] = useState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);

  setInterval(() => {
    changeState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);
  }, 2000);

  return (
    <div className="App">
      <PersonalInfo title={state} />
    </div>
  );
}

export default App;
function PersonalInfo({ title}) {
    return <div>
        <h1>I Love {title} </h1>
    </div>
}

export default PersonalInfo

CodePudding user response:

    import PersonalInfo from './PersonalInfo.js'
    import { useState } from 'react';
    
    function App() {
      const myPersonalInfo = ['books', 'music', 'code']; 
      const [state, changeState] = useState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);
    
      useEffect(() => {
         setInterval(() => {
            changeState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);
         }, 2000);
      }, [])
    
      return (
        <div className="App">
          <PersonalInfo title={state} />
        </div>
      );
    }
    
    export default App;

Use useEffect hook

CodePudding user response:

Use react useEffect

useEffect with empty dependency only run on first render

clear interval on component unmount

import PersonalInfo from './PersonalInfo.js'
import React, { useState, useEffect } from 'react';

function App() {
  const myPersonalInfo = ['books', 'music', 'code']; 
  const [state, changeState] = useState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);

  useEffect(() => {
    const intervalId = setInterval(() => {
      changeState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);
    }, 2000);
    
    return () => clearInterval(intervalId)
  }, [])

  return (
    <div className="App">
      <PersonalInfo title={state} />
    </div>
  );
}

export default App;

CodePudding user response:

Use useEffect and set state as a dependency.

useEffect(() => {
  setInterval(() => {
    changeState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);
  }, 2000);
}}, [state])

CodePudding user response:

You would wanna use useEffect with an empty decencies array, to ensure that the code for setting the interval runs only once on mount, as otherwise you create in memory a new interval on every state changes. Also you wanna clear that interval when your component is being destroyed.

Finally you would wanna use a function to update the state, as otherwise, you will register in memory a set interval that will keep updating the state with the same value, the first random one. The state updater function make sure you hydrate the interval with a new value evrytime.

port PersonalInfo from './PersonalInfo.js'
import { useState } from 'react';

function App() {
  const myPersonalInfo = ['books', 'music', 'code']; 
  const [state, changeState] = useState(myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);

  
  
  useEffect(()=>{
   const id = setInterval(() => {
       changeState(prev => myPersonalInfo[Math.floor(Math.random() * myPersonalInfo.length)]);
    }, 2000);
    
    // clear the interval before the component gets unmounted
    return ()=>clearInterval(id);
  
  },[])

  return (
    <div className="App">
      <PersonalInfo title={state} />
    </div>
  );
}

export default App;
  • Related