React 只重新渲染一个 setState 而不是另一个
React only re-rendering one setState but not the other
我正在用 React 创建一个简单的井字游戏。
目标:
每个按钮都有自己的状态。单击按钮后,它应将状态从“”切换为 'X',然后将播放器的全局状态更改为 'Player 2'。
问题:
它只是重新呈现 setPlayer() 调用而不是 setValue() 调用。但我摆脱了 setPlayer() 并只调用 setValue(),然后它按预期工作。我需要 setStates 才能工作并重新渲染,以便在玩家名称更改时显示 X。
这是一个 link 到实时沙盒版本 -
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;
您的代码存在的问题是您在渲染过程中创建了全新类型的组件 App
。这行不通。例如,每次 App
渲染时,都会创建一个新函数 Buttons
。它可能与原始函数具有相同的文本,但所有 React 都知道它与上次不同。因此,由于它是一种不同类型的组件,因此 react 会卸载旧组件并安装新组件,从而清除所有状态。
您想要定义的任何组件都需要移到 App
之外,这样您只需创建一次,而不是在每次渲染时都创建它这肯定包括 Buttons
,因为它有状态,虽然您可以将 WhosTurnMessage
和 MapButtons
移出,但我认为它们不应该成为组成部分。我只想 App
计算 jsx 本身的那些位。
因此,如果您仍想将组件的某些部分分配给局部变量,我建议这样做:
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
}
或者就个人而言,我会在线执行 jsx,而不将其分配给变量:
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>
)
}
我正在用 React 创建一个简单的井字游戏。
目标: 每个按钮都有自己的状态。单击按钮后,它应将状态从“”切换为 'X',然后将播放器的全局状态更改为 'Player 2'。
问题: 它只是重新呈现 setPlayer() 调用而不是 setValue() 调用。但我摆脱了 setPlayer() 并只调用 setValue(),然后它按预期工作。我需要 setStates 才能工作并重新渲染,以便在玩家名称更改时显示 X。
这是一个 link 到实时沙盒版本 -
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;
您的代码存在的问题是您在渲染过程中创建了全新类型的组件 App
。这行不通。例如,每次 App
渲染时,都会创建一个新函数 Buttons
。它可能与原始函数具有相同的文本,但所有 React 都知道它与上次不同。因此,由于它是一种不同类型的组件,因此 react 会卸载旧组件并安装新组件,从而清除所有状态。
您想要定义的任何组件都需要移到 App
之外,这样您只需创建一次,而不是在每次渲染时都创建它这肯定包括 Buttons
,因为它有状态,虽然您可以将 WhosTurnMessage
和 MapButtons
移出,但我认为它们不应该成为组成部分。我只想 App
计算 jsx 本身的那些位。
因此,如果您仍想将组件的某些部分分配给局部变量,我建议这样做:
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
}
或者就个人而言,我会在线执行 jsx,而不将其分配给变量:
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>
)
}