Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

88
Visualizações
React only re-rendering one setState but not the other

I'm creating a simple Tic Tac Toe game in React.

The Goal: Each button has it's own state. After the button has been clicked it should switch the state from ' ' to an 'X' and then change the global state for player to say 'Player 2'.

The Problem: It's only re-rendering the setPlayer() call but not the setValue() call. But I'f I get rid of setPlayer() and only call setValue(), then it works as intended. I need both setStates to work and re-render so that an X is displayed the the player name changes.

Here is a link to a live sandbox version -
https://codesandbox.io/s/ticktacktoe-ozxjm?file=/src/App.js

import './App.css';
import { useState } from 'react';

function App() {

  const player1 = "Player 1"
  const player2 = "Player 2"
  const [player, setPlayer] = useState(player1)
 

  const WhosTurnMessage =()=>(
    <div className='message'>
      {player}, It's Your Turn
    </div>
  )


  const Buttons =()=>{
    const [value, setValue] = useState()

    const checkAndSet =()=>{
      if (player === player1){
        setValue('X')
        setPlayer(player2)
      }
      else {
        setValue('O')
        setPlayer(player1)
      }
    }

    return (
      <div className='grid-item'>
        <button className='btn' onClick={()=>checkAndSet()} > 
          {value} 
        </button>
      </div>
    )
  }

  const MapButtons =()=>(
    [1,2,3,4,5,6,7,8,9].map( i =>  <Buttons key={`button ${i}`}/>)
  )


  return (
    <div className="App">
      <header className="App-header">
        <h1>
          Tick Tack Toe 
        </h1>
      </header>

      <WhosTurnMessage />
      
      <main>
        <div className='grid-container'>

        <MapButtons />
          
        </div>
      </main>
    </div>
  );
}

export default App;
about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

The problem with your code is that you're creating brand new types of components in the middle of rendering App. This won't work. For example, every time App renders, a new function Buttons is created. It may have the same text as the original function, but all react knows is that it's a different function from the last time. So since it's a different type of component, react unmounts the old one, and mounts the new one, wiping out all state.

Any component that you want to define needs to be moved outside of App, so that you just create it once, not on every render This definitely includes Buttons, since it has state, and while you could move WhosTurnMessage and MapButtons out, i don't think those deserve to be components. I would just have App calculate those bits of jsx itself.

So, i recommend this, if you still want to assign parts of the component to local variables:

function App() {
  const player1 = "Player 1"
  const player2 = "Player 2"
  const [player, setPlayer] = useState(player1)
 
  const whosTurnMessage = (
    <div className='message'>
      {player}, It's Your Turn
    </div>
  );

  const mapButtons = [1,2,3,4,5,6,7,8,9].map( i =>  <Buttons key={`button ${i}`}/>)

  return (
    <div className="App">
      <header className="App-header">
        <h1>
          Tick Tack Toe 
        </h1>
      </header>
        {whosTurnMessage}
      <main>
        <div className='grid-container'>
          {mapButtons}
        </div>
      </main>
    </div>
  )
}

const Buttons = () => {
  const [value, setValue] = useState();
  // ... same code you already have
}

Or personally, i would do the jsx in line, without assigning it to variables:

function App() {
  const player1 = "Player 1"
  const player2 = "Player 2"
  const [player, setPlayer] = useState(player1)

  return (
    <div className="App">
      <header className="App-header">
        <h1>
          Tick Tack Toe 
        </h1>
      </header>
      <div className='message'>
        {player}, It's Your Turn
      </div>
      <main>
        <div className='grid-container'>
          {[1,2,3,4,5,6,7,8,9].map(i => <Buttons key={`button ${i}`}/>)}
        </div>
      </main>
    </div>
  )
}
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda