reactjs 在构造函数与属性中存储状态

IT技术 javascript reactjs
2021-05-15 16:15:25

我有一个非常简单的react组件,它需要连接到 API 并检索一些 JSON 数据,然后这些数据将用于显示一些信息。

在以下类/组件中,我将mountedstate作为属性。我通常使用构造函数来保存我的状态,但在这种情况下,如果我将状态移动到构造函数,我似乎无法访问projectInfo渲染器中的数据 ( )。在渲染器(包含行{projectInfo.name})中时,我收到错误:TypeError:无法读取 null 的属性“名称”

如何使用此类中的构造函数来保存状态?为什么下面的类可以工作,但当我使用构造函数时却不能工作?处理这样的事情的惯例是什么?

class MyReportSummary extends Component {
  mounted = true;
  state = {
    projectInfo: null,
    isLoading: true,
    error: null
  };

  componentDidMount() {
    fetch(`/api/projects/${this.props.projectId}`)
      .then(response => {
        if (response.ok) {
          return response.json();
        } else {
          throw new Error("Encountered problem fetching project info");
        }
      })
      .then(data => {
        if (this.mounted) {
          this.setState({
            projectInfo: data
          });
        }
      })
      .catch(fetchError => {
        if (this.mounted) {
          this.setState({
            isLoading: false,
            error: fetchError
          });
        }
      });
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  render() {
    const { isLoading, error, projectInfo } = this.state;

    if (error) {
      return <p>{error.message}</p>;
    }

    if (isLoading) {
      return <p>Loading...</p>;
    }

    return (
      <div className="myReportSummary">
        Summary of Project name: {projectInfo.name}
        Number of events: {this.props.data.length}
      </div>
    );
  }
}

更新:为了清楚起见,上面的示例代码工作得很好。我想了解的是,如果我的类看起来像这样,具有构造函数初始化状态,那么我会得到TypeError

class MyReportSummary extends Component {
  mounted = true;

  constructor(props) {
    super(props);

    this.state = {
        projectInfo: null,
        isLoading: false,
        error: null
    };
  }

  componentDidMount() {
    // same as the previous sample code
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  render() {
    //same as the previous sample code
  }
}

国家的正确约定是什么?constructor不是这样做的正确方法?

1个回答

像您的第二个示例一样在构造函数中初始化状态是完全有效的,但是您的两个示例并不相同。要设置isLoadingtrue的类属性的版本,但isLoadingfalse在构造函数中。

如果errorinnullisLoadingis,false您将点击渲染方法的最后一部分。由于projectInfonull在你的请求完成,你会尝试访问namenull,让你的错误。

设置isLoadingtrue,它应该按预期工作,甚至projectInfo是一个空对象{},但是你不会得到加载指示器。

class MyReportSummary extends Component {
  constructor(props) {
    super(props);

    this.mounted = true;
    this.state = {
      projectInfo: {},
      isLoading: true,
      error: null
    };
  }

  // ...
}