Home > OS >  React(Next.js) Set Timeout and useState not doing as should
React(Next.js) Set Timeout and useState not doing as should

Time:08-25

So I basically want a tag that looks like this.

This is <a href="https://nextjs.org">tyty<span> {textArray[Index]}</span></a>

and I want textArray[Index] to show a different value every 3 seconds. Currently my code cycles through the array, however, it seems to gofrom Array 0 to Array 2 then Array 4.

I want it to Show array 0 then 3 seconds later array 1, 3 secs, array 2, 3 secs, array 3, then back to array 0 and repeat.

My code looks like this:

  const textArray = [
    "digital",
    "development",
    "graphics",
    "blog"
  ] 

const [Index, setIndex] = useState(0);

  const intervalID = setTimeout(changeText, 3000);

  function changeText(){
    if(Index >= 0 && Index < 4) {
    setIndex((prevIndex) =>   prevIndex);
    } 

    if(Index > 3){
        setIndex((prevIndex) => prevIndex=0);
    }
  }

Why can't I also seem to get it to go through array 1 and array 3.

When I go to google dev mode, I type in Index into the console and it says its not defined. Same with textArray.

CodePudding user response:

First - memoize your array or other objects using useState or useMemo. Without that - objects and arrays will be recreated on each render. And if for primitives like boolean, numbers, strings it is - ok and depsArrays of useMemo and useEffect will handle them right - for arrays and object it will not be ok due to even if object is the same in terms of values - reference to this object will be changed (new object created) and that will cause pretty bad behavior and tons of unneded re-renders, especially if you pass those objects and arrays down to the child components.

Next - it is setInterval, not setTimeout.

Last - always clear Intervals you created.

import { useState, useEffect, useMemo } from "react";

export default function App() {
  // memoize the array and dont recreate it on each render
  const textArray = useMemo(
    () => ["digital", "development", "graphics", "blog"],
    []
  );
  const [index, setIndex] = useState(0);

  // Will be recalculated when index or textArray changed
  const text = useMemo(() => {
    return textArray[index];
  }, [index, textArray]);

  useEffect(() => {
    // setInterval, not the setTimeout
    const intervalId = setInterval(() => {
      // Index will go up but % will cut it down
      setIndex((prev) => (prev   1) % textArray.length);
    }, 3000);

    return () => clearInterval(intervalId);
  }, [textArray]);

  return (
    <div className="App">
      This is{" "}
      <a href="https://nextjs.org">
        tyty<span> {text}</span>
      </a>
    </div>
  );
}

Edit laughing-currying-nlhhze

  • Related