在我的剪刀石头布应用程序中,PcRandomChoice有时不更新功能,而是更新为新的选择。我的用户选择有时也会发生相同的情况。我究竟做错了什么?我可以使用我的codeandbox链接进行更新。这是状态管理问题吗?当您console.log选择时,它会显示随机用户选择正在更新,而不更新其他变量。
import React, { Component } from "react";
import ReactInfo from "./ResultInfo";
import { ScoreAlert } from "./Alert";
import { Button, Container, Row, Col } from "react-bootstrap";
import { weapons } from "./data";
const WeaponButton = props => {
const { name, id, attackAction } = props;
return (
<Button
onClick={() => attackAction(id)}
className="myButton"
variant="outline-primary"
size="md"
>
{name}
</Button>
);
};
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 10,
ran: "",
id: "",
temp: Math.floor(Math.random() * 3 + 1),
draw: {
score: 0
},
user: {
score: 0,
choice: ""
},
pc: {
score: 0,
choice: ""
},
roundLimit: 10,
roundWinner: ""
};
this.setWinner = this.setWinner.bind(this);
this.setWeapon = this.setWeapon.bind(this);
this.battle = this.battle.bind(this);
this.attack = this.attack.bind(this);
}
setWeapon = (pcId, userId) => {
const [ pcWeaponName, userWeaponName] = [pcId, userId].map(weaponId => weapons.find(w => w.weaponId === weaponId).name);
console.log(this.state.pc.choice, pcWeaponName)
this.setState({
user: { score: this.state.user.score, choice: userWeaponName },
pc: { score: this.state.pc.score, choice: pcWeaponName }
});
};
setWinner = (winner = "draw") => {
const { score, choice } = this.state[winner];
const newScore = score + 1;
this.setState({
roundWinner: winner,
[winner]: { score: newScore, choice }
});
};
battle = userWeaponId => {
//Get PC Choice
const generatePcWeapon = () =>
[...weapons][Math.floor(Math.random() * weapons.length)];
const pcWeapon = generatePcWeapon();
const { weaponId: pcWeaponId, weaknesses = [] } = pcWeapon;
// Get User Choice
// Compare IDs
if (pcWeaponId === userWeaponId) {
// Update roundWinner to Draw
this.setWinner();
// Return
return;
}
// Search for user choice in PC Weaknesses
this.setWeapon(pcWeaponId, userWeaponId);
const winner = weaknesses.includes(userWeaponId) ? "user" : "pc";
this.setWinner(winner);
};
attack = id => {
this.battle(id); // your alert function
};
render(props) {
const { user, pc, roundWinner } = this.state;
return (
<>
<div className="container">
<Container fluid>
<Row>
<Col>
<h5>Rock, Paper, Scissors</h5>
</Col>
</Row>
<Row>
<Col>
<h6> Select Your Weapon </h6>
</Col>
</Row>
{weapons.map(({ name, weaponId }) => {
return (
<Row key={weaponId}>
<Col>
<WeaponButton
attackAction={this.attack}
id={weaponId}
name={name}
/>
</Col>
</Row>
);
})}{" "}
</Container>
</div>
<ReactInfo
id={user.choice}
ran={pc.choice}
roundWinner={roundWinner}
userPoint={user.score}
pcPoint={pc.score}
/>
</>
);
}
}
export default Counter;
答案 0 :(得分:1)
您的状态不浅,即您在对象内部有对象。当检测到状态变化时,将进行浅表比较。要阻止这种情况的发生,您应该在设置状态之前对其进行复制。 一个简单的方法是JSON.Stringify和JSON.parse。这是占用大量CPU的资源,但在此代码中不应成为问题,因为它不是很复杂。
setWinner = (winner = "draw") => {
const { score, choice } = this.state[winner];
const newScore = score + 1;
const stateCopy = JSON.parse(JSON.stringify({
roundWinner: winner,
[winner]: { score: newScore, choice }
}))
this.setState(stateCopy);
};
setWeapon = (pcId, userId) => {
const [ pcWeaponName, userWeaponName] = [pcId, userId].map(weaponId => weapons.find(w => w.weaponId === weaponId).name);
console.log(this.state.pc.choice, pcWeaponName)
const stateCopy = JSON.parse(JSON.stringify({
user: { score: this.state.user.score, choice: userWeaponName },
pc: { score: this.state.pc.score, choice: pcWeaponName }
}))
this.setState(stateCopy);
};
一种更好的方法是将对象散开,使其始终是新对象,您也可能希望散布内部对象,因为使用散布时它也会进行浅表复制。但是您需要在自己的代码中进行测试以进行测试。
setWinner = (winner = "draw") => {
const { score, choice } = this.state[winner];
const newScore = score + 1;
const stateCopy = {
roundWinner: winner,
[winner]: { score: newScore, choice }
}
this.setState({...stateCopy});
};
setWeapon = (pcId, userId) => {
const [ pcWeaponName, userWeaponName] = [pcId, userId].map(weaponId => weapons.find(w => w.weaponId === weaponId).name);
console.log(this.state.pc.choice, pcWeaponName)
const stateCopy = {
user: { score: this.state.user.score, choice: userWeaponName },
pc: { score: this.state.pc.score, choice: pcWeaponName }
}
this.setState({...stateCopy});
};