【问题标题】:What happens to 'remaining' code execution on component re-render?组件重新渲染时“剩余”代码执行会发生什么?
【发布时间】:2019-04-06 12:35:11
【问题描述】:

使用 React.js,假设我有一个父组件,它有一个状态列表:

myList: [1, 2, 3]

我在myList 上执行 .map(),并为列表中的每个项目呈现一个新组件。所以我的父应用现在有了子组件。

假设在这个子组件内部,我运行了一个方法myMethod,并在这个方法中间的某个地方更新了父组件的myList 状态变量。

这将触发子组件(包括当前组件)的重新渲染(对吗?),它正在执行myMethod,但还没有执行完该方法的所有行。

主要问题:

myMethod 方法内的任何剩余代码行会发生在导致方法组件重新渲染的行之后的代码行吗?

(他们还会被执行,还是会中止执行?比这更微妙的东西?)

【问题讨论】:

  • 他们为什么会中止?您还遇到了具体问题,还是只是一般问题?
  • 不应该是无限循环吗?子级更新父级的状态,父级再次重新渲染其子级
  • 我想任何剩余的代码都将被中止,因为组件将重新渲染。但是我不知道 React 在那个级别上是如何工作的,所以我不知道,这就是我问的原因。我有一个特定的情况,我想首先更新一些父组件的状态,触发子组件的重新渲染,而子组件仍然需要执行一些代码,包括对后端的 axios 请求。
  • setState 是异步的,因此它不会立即更新您的父组件状态。因此,方法myMethod 中的剩余代码不会被中止。所有剩余的代码都被执行,并且只有在父组件状态被更新并且这将触发重新渲染之后。而且,如果您愿意,您还可以在相同的 myMethod 方法中更新子组件状态(在解决您对后端的 axios 请求后)。

标签: javascript reactjs


【解决方案1】:

setState 是异步的,因此它不会立即更新您的父组件状态。因此,方法myMethod 中的剩余代码不会被中止。所有剩余的代码都被执行,并且只有在父组件状态被更新并且这将触发重新渲染之后。而且,如果您愿意,您可以在相同的myMethod 方法中更新子组件状态(在解决您对后端的 axios 请求后)。

例如:

import React, { Component } from "react";
import ReactDOM from "react-dom";

const getRandomInt = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1)) + min;
};

class Parent extends Component {
  state = {
    list: [1, 2, 3]
  };

  parentHandler = value => {
    this.setState({ list: [...this.state.list, value] }, () =>
      console.log("parent component state updated")
    );
  };

  render() {
    return (
      <div>
        {this.state.list.map(item => (
          <Child key={item} item={item} parentHandler={this.parentHandler} />
        ))}
      </div>
    );
  }
}

class Child extends Component {
  state = {
    id: 24
  };

  fakePromsise = () => {
    const newId = getRandomInt(24, 60);
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(newId), 5000);
    });
  };

  childHandler = listItem => {
    let newItem = listItem + getRandomInt(10, 1000);
    // handling parent state
    this.props.parentHandler(newItem);
    // handling fake promise
    // and when the promise resolves
    // update the component state
    this.fakePromsise().then(data =>
      this.setState(
        {
          id: data
        },
        () => console.log("child component state updated")
      )
    );
    // after the loop completes
    // parent state is updated
    for (let i = 0; i < 5000; i++) {
      console.log("i", i);
    }
  };

  render() {
    return (
      <div>
        <h1 onClick={() => this.childHandler(this.props.item)}>
          {this.props.item} click me!!!
        </h1>
        <p>Id: {this.state.id}</p>
      </div>
    );
  }
}

ReactDOM.render(<Parent />, document.getElementById('root'));

您可以使用该示例并查看控制台结果。只需单击h1 标签。之后添加新的Child 组件并更改单击的Child 组件id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 2020-11-04
    • 2023-02-20
    • 1970-01-01
    • 2022-08-10
    • 2020-02-13
    相关资源
    最近更新 更多