在第一次渲染期间处理组件中的未定义/空属性

Rob*_*son 9 javascript reactjs

我正在学习反应,它很棒,但我遇到了一个问题,我不确定解决它的最佳实践是什么。

我正在从我的 componentDidMount() 中的 API 获取数据,然后我使用 SetState() 设置一些状态。

现在的问题是,因为第一次渲染发生在我的状态设置之前,所以我将初始状态值发送到我的组件中。现在我将它们设置为空数组或空对象({ type: Object, default: () => ({}) })。然后我使用三元运算符来检查 .length 或者属性是否有值。

这是最佳做法还是我不知道的其他方法?

我很想得到一些帮助,以便我从一开始就正确地做基础知识。

谢谢!

poo*_*a72 10

我认为最好的做法是告诉用户您的数据仍在加载,然后用真实数据填充字段。这种方法已在各种博客文章中得到提倡。Robin Wieruch 写了一篇关于如何获取数据的精彩文章,并提供了一个关于如何处理加载数据和错误的具体示例,我将在这里介绍他的示例。这种方法通常分两部分完成。

  1. 创建一个isLoading变量。这是一个bolean. 我们最初将其设置为false,因为没有加载任何内容,然后true在我们尝试获取数据时将其设置为 ,然后在加载数据后返回false
  2. 我们必须告诉 React 在这两种isLoading状态下要渲染什么。

1.设置isLoading变量

由于您没有提供任何代码,我将只遵循 Wieruch 的示例。

import React, { Component } from 'react';

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

    this.state = {
      dataFromApi: null,
    };
  }

  componentDidMount() {
    fetch('https://api.mydomain.com')
      .then(response => response.json())
      .then(data => this.setState({ dataFromApi: data.dataFromApi }));
  }

  ...
}

export default App;
Run Code Online (Sandbox Code Playgroud)

这里我们使用浏览器的原生fetch()api来获取组件通过使用componentDidMount(). 这应该与您现在所做的非常相似。鉴于该fetch()方法是异步的,页面的其余部分将呈现并且状态将在接收到数据后更新。

为了告诉用户我们正在等待数据加载,我们只需添加isLoading到我们的状态。所以状态变成:

this.state = {
  dataFromApi: null,
  isLoading: false,
};
Run Code Online (Sandbox Code Playgroud)

状态 forisLoading最初false是因为我们还没有调用fetch()。在我们调用fetch()inside之前,我们componentDidMount()将状态设置isLoading为 true,如下所示:

this.setState({ isLoading: true });
Run Code Online (Sandbox Code Playgroud)

然后,我们需要向我们的fetch()Promise添加一个 then() 方法,isLoadingfalse在数据加载完成后将状态设置为to 。

.then(data => this.setState({ dataFromAPi: data.dataFromApi, isLoading: false }));
Run Code Online (Sandbox Code Playgroud)

最终代码如下所示:

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

    this.state = {
      dataFromApi: [],
      isLoading: false,
    };
  }

  componentDidMount() {
    this.setState({ isLoading: true });

    fetch('https://api.mydomain.com')
      .then(response => response.json())
      .then(data => this.setState({ dataFromApi: data.dataFromApi, isLoading: false }));
  }

  ...
}

export default App;
Run Code Online (Sandbox Code Playgroud)

2. 条件渲染

React 允许条件渲染。我们可以if在我们的render()方法中使用一个简单的语句来根据 的状态渲染组件isLoading

class App extends Component {
  ...

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

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

    return (
      <ul>
        {dataFromApi.map(data =>
          <li key={data.objectID}>
            <a href={data.url}>{data.title}</a>
          </li>
        )}
      </ul>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。