Handling undefined/null properties in components during first render

后端 未结 3 824
春和景丽
春和景丽 2021-01-13 01:28

I\'m learning react and it\'s great, but i\'ve ran into an issue and i\'m not sure what the best practice is to solve it.

I\'m fetching data from an API in my compon

3条回答
  •  天涯浪人
    2021-01-13 01:50

    I think the best practice is to tell the user that your data is still loading, then populate the fields with the real data. This approach has been advocated in various blog-posts. Robin Wieruch has a great write up on how to fetch data, with a specific example on how to handle loading data and errors and I will go through his example here. This approach is generally done in two parts.

    1. Create an isLoading variable. This is a bolean. We initially set it to false, because nothing is loading, then set it to true when we try to fetch the data, and then back to false once the data is loaded.
    2. We have to tell React what to render given the two isLoading states.

    1. Setting the isLoading variable

    Since you did not provide any code, I'll just follow Wieruch's example.

    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;
    

    Here we are using the browser's native fetch() api to get the data when the component mounts via the use of componentDidMount(). This should be quite similar to what you are doing now. Given that the fetch() method is asynchronous, the rest of the page will render and the state will be up dated once the data is received.

    In order to tell the user that we are waiting for data to load, we simply add isLoading to our state. so the state becomes:

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

    The state for isLoading is initially false because we haven't called fetch() yet. Right before we call fetch() inside componentDidMount() we set the state of isLoading to true, as such:

    this.setState({ isLoading: true });
    

    We then need to add a then() method to our fetch() Promise to set the state of isLoading to false, once the data has finished loading.

    .then(data => this.setState({ dataFromAPi: data.dataFromApi, isLoading: false }));
    

    The final code looks like this:

    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;
    

    2. Conditional Rendering

    React allows for conditional rendering. We can use a simple if statement in our render() method to render the component based on the state of isLoading.

    class App extends Component {
      ...
    
      render() {
        const { hits, isLoading } = this.state;
    
        if (isLoading) {
          return 

    Loading ...

    ; } return ( ); } }

    Hope this helps.

提交回复
热议问题