最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Warning: Cannot update a component (`App`) while rendering a different component (`History`) - Stack Overflow

programmeradmin1浏览0评论

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 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 "./ponents/Board"
import History from "./ponents/History"
import {calculateWinner} from './support'
import StatusMessage from './ponents/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

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. 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 "./ponents/Board"
import History from "./ponents/History"
import {calculateWinner} from './support'
import StatusMessage from './ponents/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

Share Improve this question asked Jun 3, 2021 at 4:07 Tayyab aliTayyab ali 411 gold badge2 silver badges10 bronze badges 2
  • Please give me a code sandbox to run the app – Brian Commented Jun 3, 2021 at 4:34
  • @ChanghoonLee codesandbox.io/s/youthful-mirzakhani-nm7kp?file=/src/ponents/… – Tayyab ali Commented Jun 3, 2021 at 5:01
Add a ment  | 

2 Answers 2

Reset to default 5

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 ponent, it also inadvertently calls the moveTo function which triggers an update in the App ponent. This is what the error says - can't update another ponent while rendering a ponent.

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/ponents/History.js

In React Navigation move the setParams and setOptions inside method ponentDidMount() in class ponents or in useEffects() hook in functional ponents.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论