reactjsrandomnext.jsuse-effectserver-side-rendering

Randomize an array using useEffect in Nextjs


I'd like to randomize an array everytime the page is loaded. I'm using Nextjs and the first issue is that client and server don't match, so I've been advised I need to put the randomize code inside a useEffect hook, but I'm obviously doing it wrong... i'd like some help to understand how to fix my code please.

export default function IndexPage() {
  useEffect(()=>{
    let randomizeArray = [...array].sort(() => 0.5 - Math.random());

    let selectedRandomArray = randomizeArray.slice(0, 3);
  },[])

  return (
    <div>
      {selectedRandomArray.map((s, id) => (
        <div key={id}>
          <h2>{s.name}</h2>
        </div>
      ))}
    </div>
  );
}

Here is the example in Codesandbox without the useEffect. It works but I´m getting unmatched client/server in console https://codesandbox.io/s/shuffle-array-and-return-random-values-in-nextjs-veqy3w?file=/pages/index.js


Solution

  • In addition to moving the randomise logic inside a useEffect, you have to create a state variable (randomArray) and store the randomised array into it (setRandomArray()). This will trigger a component re-render and display the updated UI.

    const array = [{ name: 1 }, { name: 2 }, { name: 3 }, { name: 4 }, { name: 5 }];
    
    export default function IndexPage() {
        const [randomArray, setRandomArray] = useState([]);
        
        useEffect(() => {
            const randomizeArray = [...array].sort(() => 0.5 - Math.random());
            setRandomArray(randomizeArray.slice(0, 3));
        }, []);
    
        return (
            <div>
                {randomArray.map((s, id) => (
                    <div key={id}>
                        <h2>{s.name}</h2>
                    </div>
                ))}
            </div>
        );
    }