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

时间:2018-07-16 18:54:58

标签: javascript reactjs

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

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

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

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 个答案:

答案 0 :(得分:1)

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

如果error中的null并且isLoadingfalse,您将点击渲染方法的最后一部分。由于在您的请求完成之前projectInfonull,所以您将尝试访问name上的null并收到错误消息。

isLoading设置为true,它应该可以按预期运行,甚至可以将projectInfo设置为空对象{},但是这样您将无法获得加载指示器。 / p>

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

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

  // ...
}