为什么此代码会进入无限循环

时间:2019-09-12 04:09:39

标签: reactjs spring http

我有一个React应用,它的作用是选择自己的冒险事物,因此它会打印一条消息,然后用户单击一个按钮做出决定,然后确定下一条消息。

某些消息没有相关的决策,新消息应该自动打印出来。在我当前的设置下,当用户必须单击一个按钮以显示下一条消息时,它可以很好地工作,但是当应该自动显示该消息时,它实际上是在重复显示下一条消息,直到崩溃为止。

我尝试了很多事情都给出相同的结果,应该只显示一次的消息会显示多次,直到应用程序崩溃为止。

请注意,决策的工作方式是将整数列表(每个整数代表下一个孩子的名字)发送到服务器,然后使用该列表遍历一棵树-就像我说的那样当玩家选择一个按钮,然后根据选择的按钮向列表添加一个整数时,效果很好。

当没有按钮时,我试图建立一种方法,该方法会自动将0自动添加到列表中(因为如果没有选择,它只有一个孩子,第0个孩子)。 / p>

这是我的代码,有按钮时使用onDecide方法,无按钮时使用onNonDecide方法-我本来只是尝试使用onDecide方法并尝试将它们分开以查看是否可行,但还是存在相同的问题。

还要注意generateDecisions方法,因为它有一个if语句,该语句在没有决定要更改时会改变行为。

class Home extends Component {
  constructor(props) {
    super(props);
    this.state = {
      previouslyPlayed: [],
      currentNode: {
        id: 1,
        text: 'Ah-- what the hell? Stupid thing.',
        decisions: [
          {
            id: 'n1d1',
            text: 'Who is this?',
            whichChild: 0,
            attitude: 0
          },
          {
            id: 'n1d2',
            text: 'What the hell yourself.',
            whichChild: 0,
            attitude: 0
          }
        ],
        speaker: 0,
        checkpoint: true
      },
      decisionList: [0]
    };

    this.onDecide = this.onDecide.bind(this);
    this.onNonDecide = this.onNonDecide.bind(this);

  }

  // Generate the previous messages to be displayed on the screen
  generateMessages() {
    let currentPrevious = this.state.previouslyPlayed;
    if (currentPrevious.indexOf(this.state.currentNode.text) < 0) {
      currentPrevious.push(this.state.currentNode.text);
    }

    return currentPrevious.map((text) =>
      <Message key={currentPrevious.indexOf(text)} text={text}/>
    );
  }

  // Generate the current decision that the play must make
  generateDecision() {
    if (this.state.currentNode.decisions.length <= 0) {
      let ignore = this.onNonDecide();
    } else {
      return <Decision decisions={this.state.currentNode.decisions} onDecide={this.onDecide}/>;
    }
  }

  updatePreviouslyPlayed(text) {
    let previouslyPlayed = this.state.previouslyPlayed;
    previouslyPlayed.push(text);
    this.setState({previouslyPlayed: previouslyPlayed});
  }

  updateDecisionList(whichChild) {
    let decisionList = this.state.decisionList;
    decisionList.push(whichChild);
    this.setState({decisionList: decisionList});
  }

  async onDecide(answer) {
    //Update the state to reflect the decision made
    this.updatePreviouslyPlayed(answer.text);
    this.updateDecisionList(answer.whichChild);

    let body = { decisionList: this.state.decisionList };

    let currentNode = await (await fetch('http://localhost:8080/decide', {
      method: 'POST',
      mode: 'cors',
      headers: {
        'Accept': 'application/json',
        'Cache-Control': 'no-cache',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      },
      body: JSON.stringify(body),
    })).json();
    this.setState({currentNode: currentNode});
  }

  async onNonDecide() {
    this.updateDecisionList(0);

    let body = { decisionList: this.state.decisionList }

    let currentNode = await (await fetch('http://localhost:8080/decide', {
      method: 'POST',
      mode: 'cors',
      headers: {
        'Accept': 'application/json',
        'Cache-Control': 'no-cache',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      },
      body: JSON.stringify(body),
    })).json();
    this.setState({currentNode: currentNode});
  }

  render() {
    return (
      <div>
        <Container id={'Application'}>
          {this.generateMessages()}
          {this.generateDecision()}
        </Container>
      </div>
    );
  }
}

export default Home;

我要执行的操作是一次设置currentNode,然后调用generateMessagesgenerateDecisions,然后打印出新的Message,并可能新的Decision。它要做的是开始相同的Message打印数百次。

1 个答案:

答案 0 :(得分:2)

问题在于您有副作用,这些副作用会改变在render方法中调用的状态。

  

render()函数应该是纯函数,这意味着它不会修改组件状态,每次调用时都返回相同的结果,并且不与浏览器直接交互。 -React Docs

例如,此路径render() -> this.generateDecision() -> this.onNonDecide() -> this.setState() -> render() (重复一遍,可能是一个无限循环,我没有考虑所有可能的路径,仅举一个例子)。

您可能会遇到的另一个问题是,没有发生重新渲染或其他意外行为,就像在generateMessages中那样发生了突变状态。 previouslyPlayed数组已被currentPrevious.push突变。