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
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