Home > other >  a function that supposed to return a different value each time does not work in react
a function that supposed to return a different value each time does not work in react

Time:09-01

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:

  1. Whenever there's a change in the value of a local state.
  2. 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()
  • Related