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;