Warning: Cannot update a component (`App`) while rendering a different component (`History`)

I am actually building a tic tac toe. But this error is not actually letting me update history. As I am following a tutorial on skillshare.com and I did the same as he does. But still getting error. I am a beginner in React. And I use a nano-react npm project for creating this project. This is App.js:

import React , {useState} from "react";
import Board from "./components/Board"
import History from "./components/History"
import {calculateWinner} from './support'
import StatusMessage from './components/StatusMessage'
import './styles/root.scss'

const NEW_GAME = [
  {
    board: Array(9).fill(null),
    isXNext : true
  }
]
const App = () => {

  const [history, setHistory] = useState(NEW_GAME);
  const [currentMove, setCurrentMove] = useState(0);

  const current = history[currentMove];

  const {winner , winningSquare} = calculateWinner(current.board);
  
  const clickHandleFunction = (position) => {
      if (current.board[position] || winner) {
          return;
      }

      setHistory((prev) => {
        const last = prev[prev.length-1];

          const newBoard =  last.board.map((square, pos) => {
              if (pos === position) {
                  return last.isXNext ? 'X' : '0';
              }
              return square;
          });
          return prev.concat({board: newBoard, isXNext : !last.isXNext})
      });

      setCurrentMove(prev => prev +1);
  };

  const moveTo = (move) => {
    setCurrentMove(move);
  }

  const onNewGame  = () => {
    setHistory(NEW_GAME);
    setCurrentMove(0);
  }

  return(
    <div className="app">
      <h1>TIC TAC TOE</h1>
      <StatusMessage winner ={winner} current ={current}/>
      <Board board = {current.board} clickHandleFunction = {clickHandleFunction} winningSquare = {winningSquare}/>
      <button type="button" onClick = {onNewGame}>Start New Game</button>
      <History history={history} moveTo = {moveTo} currentMove = {currentMove} />
    </div>
  )
}
export default App;

And It is my History.js:

import React from 'react.'

function History({history, moveTo, currentMove}) {
    return (
        <ul>
            {
                history.map((_, move) => {
                    return( <li key={move}> <button style={{
                        fontWeight: move === currentMove ? 'bold' : 'normal'
                    }} type="button" onClick = {moveTo(move)} > 
                        {move === 0 ? 'Go to game start!': `Gove to move #${move}`} </button> </li> );
                })
            }   
        </ul>
    )
}

export default History

Full Error image with Stack Trace


Solution 1:

The problem is in History.js:

onClick={moveTo(move)}

You need to provide a function in the onClick prop. Instead, you are calling the moveTo function and passing its return value as the onClick prop.

Due to this, whenever React renders the History component, it also inadvertently calls the moveTo function which triggers an update in the App component. This is what the error says - can't update another component while rendering a component.

To fix this, change moveTo(move) to () => moveTo(move). Now you pass a function into onClick that will call the moveTo function when the user clicks. Working sandbox: https://codesandbox.io/s/practical-frog-tcyxm?file=/src/components/History.js