Next.js Discord

Discord Forum

react-hooks/rules-of-hooks

Unanswered
Dutch Smoushond posted this in #help-forum
Open in Discord
Dutch SmoushondOP
"use client";

import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";

export default function Game(props: { params: Promise<{ id: string }> }) {
  const params = React.use(props.params);
  const [moves, setMoves] = useState<number[]>([]);
  const [message, setMessage] = useState<string>();
  const [isEnd, setEnd] = useState(false);
  const router = useRouter();
  const board: string[] = "         ".split("");
  for (let i = 0; i < moves.length; i++) {
    board[moves[i] - 1] = (i % 2 == 0 ? "X" : "O");
  }
  useEffect(() => {
    const fetchData = async () => {
      const game = await fetch("/api/getGame", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          id: params.id,
        }),
      }).then((e) => e.json());
      if(game.message == "Invalid game id"){
        setMessage(game.message);
        setEnd(true);
        return;
      }
      setMoves(game.message.moves || []);
      if(game.message.result != null){
        setEnd(true);
        setMessage(game.message.result);
      }
    };
    fetchData();
  }, [params.id]);
  async function clickHandler(num: number) {
    await fetch("/api/move", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        id: params.id,
        move: num,
      }),
    })
      .then(async (e) => {
        const res = await e.json();
        if (e.status != 200) throw new Error(res.message);
        setMoves(res.message.moves || []);
        setMessage(res.message.result || "");
        if (res.message.result != null) {
          setEnd(true);
        }
      })
      .catch((error) => {
        console.log(error.text);
        setMessage(error.message);
      });
  }
  console.log(params.id);

5 Replies

Dutch SmoushondOP
i get the error
./app/[id]/page.tsx
8:29  Error: React Hook "useState" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.  react-hooks/rules-of-hooks
9:33  Error: React Hook "useState" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.  react-hooks/rules-of-hooks
10:27  Error: React Hook "useState" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.  react-hooks/rules-of-hooks
11:18  Error: React Hook "useRouter" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.  react-hooks/rules-of-hooks

info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/app/api-reference/config/eslint#disabling-rules

note that the only missing part of the code is the return(html)
First of all you should try not to setState inside an effect for many reasons, this being one of them.

The only valid place to setState in an Effect is in the promise callback

Like this, this is a simple example:
fetch(…).then(res => res.json() ).then( game => {
if (game.whatever){
setState(game)
}
…. // your other code
})

Not like this
const game = await fetch().then( res => res.json() )

if (game.whatever ) {
setState( game )
// …. your other code
}
The logic where you’re setting state should be inside the promise callback.

I would recommend you using a library like React Query to handle async queries and mutations, it’s much cleaner and helps a lot with other stuff that I didn’t even mentioned (race conditions, caching, clean ups..)

If you’re trying to build a game with react, game are made up with lots of states, so a state management library like Zustand or xState/store can definitely help you

I made a 2D web game for a class a couple months ago, I used react, but all the game state was managed with Zustand
@Dutch Smoushond i will search for these things, thank you ❤️
Of course, glad I could help 🙂