0

I am developing the game app with React + Typescript. When i refactored the App component from ClassComponent to FC, i had to use UseEffect Hook for implementing the ComponentDidMount method here. Then i had to call the function compareNumbers() when the one of the fields of state changes. Here is the problem. when i use useEffect only for mounting, the number I entered doesn't changes even when I write the state chengin in the callback. When I use UseEffect for calling comparing function, but leave the mounting, i don`t get number generation. But when I use both of them, nothin works, no number generation and no setting the number from input. And when i restart the gae by startNewGame(), number generates correctly and sets the state...

full code here: https://github.com/mykola-kolomoyets/cow-bull-react-ts

Here is fragment of code:

interface IAppState {


moves: number
  currentNumber: number
  enteredNumber: number
  gameData: {
    cows: number
    bulls: number
  }
  incorrectNumbers: number[]
  warnings: string[]
};

const App: FC = () => {
  const [data, setData] = useState<IAppState>(
    {
      moves: 0,
      currentNumber: 0,
      enteredNumber: 0,
      gameData: {
        cows: 0,
        bulls: 0
      },
      incorrectNumbers: [],
      warnings: []
    });

  // useEffect(() => {
  //   generateNumber();
  // }, []);

  // useEffect(() => {
  //   compareNumbers();
  // }, [data.enteredNumber])

  const handleCallBack = async (childData: number): Promise<void> => {
    console.log("translating the number to App");
    await setData({...data, enteredNumber: childData});
  }

  const generateNumber = (): void => {
    let digits: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let arr: number[] = [];

    for (let i = 0; i < 4; i++) {
      let index = Math.floor(Math.random() * digits.length);
      if (i === 0 && index === 0) index++;
      arr.push(digits[index]);
      digits.splice(index, 1);
    }

    setData({
      ...data,
      currentNumber: +arr.join(''),
      incorrectNumbers: digits
    });

  }
...
  const startNewGame = (): void => {
    setData({
      moves: 0,
      currentNumber: 0,
      enteredNumber: 0,
      gameData: {
        cows: 0,
        bulls: 0
      },
      incorrectNumbers: [],
      warnings: []
    });
    generateNumber();
  }
  return (
    <>
      <h1>Cow-Bull game</h1>
      <h3>React+Typescript version</h3>
      <Moves moves={data.moves} />
      <NumInput parentCallBack={handleCallBack} />
      <button onClick={startNewGame}>restart game</button>
      <WarningsContainer warnings={data.warnings} />
      <CowBulls cows={data.gameData.cows} bulls={data.gameData.bulls} />
    </>
  )
}
10
  • Whats happening probably, is your useEffect is calling an instance of that function from a previous render, can you move the function inside the useEffect? Commented Jul 5, 2021 at 10:41
  • ... or use useCallback Commented Jul 5, 2021 at 10:45
  • When i have both useEffects, the functions are called, but the State stays default (number generated but the state is not changed) When i enter the number and submit the form, number is got from the from, set to the state but while comparing it is comparing with 0 Commented Jul 5, 2021 at 10:51
  • useEffect(() => { generateNumber(); }, []); useCallback(() => { compareNumbers(); }, [data.enteredNumber]) Commented Jul 5, 2021 at 10:54
  • When i Use this, number generates, sets to the state, bit when i need compare numbers after every form submission, it doesn't... i know that useCallback has different functionality... but using two useEffect looks logically... but smth went wrong( Commented Jul 5, 2021 at 10:55

1 Answer 1

1

You need to update your code so functions that are declared in the component are wrapped in a useCallback if they are used in a useEffect.

const compareNumbers = useCallback((): void => {
    // [0] -> is 4 digits
    // [1] -> has repeated digits
    const criterias: boolean[] = [false, false];
   // ..... the rest of your function
  }, [data,setData])

This will ensure you are not using stale functions and states from old renders.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.