状态正在更新,但应用未更新/

时间:2020-06-23 09:47:14

标签: javascript reactjs

在我的剪刀石头布应用程序中,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;

1 个答案:

答案 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});
  };