I am working on my portfolio, but when I reach the experiences page I tried to create a title that has it's middle part change every second, and value of it must come from an already set up array, but when I run the code it always return the first string of the array, can anyone please fix this problem for me ?
const projectsTitleKeyWords = ['responsible', 'meaningful', 'beautiful']
let titlep2 = 'test'
let index = 0
const change = () => {
titlep2 = projectsTitleKeyWords[index]
index = index % projectsTitleKeyWords.length
setTimeout(change, 1000)
}
change()
console.log(titlep2)
const titlep1 = 'I creat '
const titlep1Array = titlep1.split('')
let titlep2Array = titlep2.split('')
const titlep3 = ' projects'
const titlep3Array = titlep3.split('')
the value of titlep2Array will be received by
<AnimatedLetters
letterClass={letterClass}
strArray={titlep2Array}
idx={15}
id='to-change'
/>
CodePudding user response:
In-order to reflect UI changes in React, a component must re-render.
A React component re-renders in 1 of 2 scenarios:
- Whenever there's a change in the value of a local state.
- Whenever any of it's parent components re-render.
Therefor, since changes in the UI are only reflected upon a re-render, we should manage a local state that would be responsible for this behavior.
With functional components in React, this can be achieved via the useState
hook.
In your case, we can simply make titlep2
a state, instead of a regular variable.
Example:
const [titlep2, setTitlep2] = useState('')
const change = () => {
setTitlep2(projectsTitleKeyWords[index])
index = index % projectsTitleKeyWords.length
setTimeout(change, 1000)
}
<AnimatedLetters
letterClass={letterClass}
strArray={titlep2.split('')}
idx={15}
id='to-change'
/>
Note: since this function now updates the state, we can't call it the way you did in your example, since it will run every time the component re-renders, making the component re-render indefinitely due to the change in state.
Therefor, we can use the useEffect
hook in-order to allow it to run only once on the initial render.
Example:
const change = () => {
setTitlep2(projectsTitleKeyWords[index])
index = index % projectsTitleKeyWords.length
setTimeout(change, 1000)
}
useEffect(() => {
change()
}, [])
- Furthermore, if there are any other variables that should reflect changes in the UI, they can be convert to states as well.
CodePudding user response:
for that try using the setInterval()
instead of setTimeout()
.
You are trying to make the text change after a specific interval in this case 1 second.
You should also consider doing that will CSS animations, it seems this is overkill.
const change = () => {
titlep2 = projectsTitleKeyWords[index]
index = index % projectsTitleKeyWords.length
console.log(titlep2)
setInterval(change, 1000)
}
change()