Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

87
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!