score:0

Accepted answer

My React component is using FetchAPI and has two return statements.

No, it doesn't. It has one:

render() {

  let theList = this.state.map((item, id) => {

    return (
      <Card>A bunch of API Stuff </Card>
    );

  })
  return (                               // <========== here
    <div className="search-wrap">
      <Row>
        {theList}
      </Row>
    </div>
  )
}

The other one is a return within your map callback, which doesn't have any effect on your render method at all.

If you want to use the conditional operator to show a loading indicator, you'd do it in your render's return:

render() {
  let { loading } = this.state; // *** Get the flag

  let theList = this.state.map((item, id) => {

    return (
      <Card>A bunch of API Stuff </Card>
    );

  })
  return (                          // *** Use it in the below
    <div className="search-wrap">
      <Row>
        {loading ? <p>Loading...</p> : theList}
      </Row>
    </div>
  )
}

You might also want to avoid the unnecessary map call, but if you know your state is initialized with an empty array, that call is harmless. But if you want to get rid of it:

render() {
  let { loading } = this.state; // *** Get the flag

  let theList = !loading && this.state.map((item, id) => {

    return (
      <Card>A bunch of API Stuff </Card>
    );

  })
  return (                          // *** Use it in the below
    <div className="search-wrap">
      <Row>
        {loading ? <p>Loading...</p> : theList}
      </Row>
    </div>
  )
}

score:0

Just add a boolean field to your state which indicates that data is being loaded.

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      loading: true, // this one
    };
  }

  componentDidMount() {
    fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({ data: data, loading: false }))
  }

  render() {

    if (this.state.loading)
       return <div>Loading...</div>

    let theList = this.state.map((item, id) => {

      return (
        <Card>A bunch of API Stuff </Card>
      );

    })
    return (
      <div className="search-wrap">
        <Row>
          {theList}
        </Row>
      </div>
    )
  }
}

export default App;

score:0

If I understand correctly, your code should look like the following:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      isLoading: false
    };
  }

  componentDidMount() {
    this.setState({ isLoading: true }); // mount the loading component when we will start the fecth
    fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({ data: data}))
      .then(() => this.setState({ isLoading: false })) // unmount Loading component when the fetch ends
  }

  render() {
    let theList = this.state.map((item, id) => {
      return (
        <Card>A bunch of API Stuff </Card>
      );
    })

    // Here we will return the Loading component as long as isLoading is true
    return (isLoading) ? <Loading /> : (
      <div className="search-wrap">
        <Row>
          {theList}
        </Row>
      </div>
    )
  }
}

export default App;

So basically we will add a boolean variable (isLoading) that will handle the state of the fetch and we will add it into the state of the component. When the fetch is triggered, this variable will be true otherwise it will be false.

So then in the return statement, we can use a ternary operator based on the value of this new variable. If it is true we will return a Loading component or a simple div saying Loading.... Otherwise we will return the App component with the data loaded.

I hope this help :)

score:0

You can do something like this. Note that you can export directly the class since the beginning. Also, you can simplify the state, without a explicit constructor. To know the fetch state, you should add a isLoading condition before and after fetching the data. Then, in the render, you can return one single node, and inside render the components that you want based on your status. With this coding style, you can even show when the fetch returns an empty array.

export default class App extends Component {
  state = {
    data: [],
    isLoading: false
  }
  componentDidMount() {
    this.setState({
      isLoading: true
    }, () => {
      fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({
        data,false
      }))
    })
  }
  render() {
    return (
      <div>
      {
        this.state.isLoading &&
        <span>
          Loading...
        </span>
      }
      {
        !this.state.isLoading &&
        (this.state.data.length > 0) &&
        <div className="search-wrap">
          <Row>
            {
              this.state.data.map((item, id) => {
                return (
                  <Card key={id}>
                    A bunch of API Stuff
                  </Card>
                );
               })
            }
          </Row>
        </div>
      }
      {
        !this.state.isLoading &&
        (this.state.data.length === 0) &&
        <span>
          There's no data to show
        </span>
      }
      </div>
    )
  }
}

Hope this helps! Denny


Related Query

More Query from same tag