0

My code below works, I used optional chaining to load information from the API. I was trying to get it to work by checking the loading state or checking if the array was empty, but I didn't have success. When I searched for "React API optional chaining", I didn't find much information specifically for these cases. The code below works, but is the way I did this considered okay? What other ways can I use to do this? What is the best way?

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      loading: true
    }
  }
  
  componentDidMount() {
    fetch('https://restcountries.eu/rest/v2/all')
      .then(response => response.json())
      .then(json => this.setState({data: json}));
    this.setState({loading: false});
  }
  
  
  render() {
    return (
      <div>
        <h1>{this.state.data?.length > 0 && this.state.data[0]["name"]}</h1>
      </div>
    )
  }
}

export default App;
phershbe
  • 169
  • 4
  • 12
  • 1
    I don't think it's very clear what you're asking. Yes, there are other and perhaps better ways to accomplish what you've accomplished here - you could rewrite your fetch pipeline using async/await syntax or rewrite the component as a functional component and use React hooks. "I was trying to get it to work by checking the loading state or checking if the array was empty, but I didn't have success." What do you mean by this? – Brendan Bond Jul 31 '21 at 22:35
  • I meant that instead of the optional chaining in the return statement, I was trying to set this.state.loading as false in the componentDidMount() and then check this.state.loading or check if the this.state.data array was empty. I'm newer to React and am trying to make stuff and get things to work and then after figure out more about why things happen and the optimal ways to do them, and I posted because I wanted to know about this and thought that other people might have the same question. – phershbe Jul 31 '21 at 22:51
  • As a side note, you could simply write `this.state.data?.[0].name` in your `h1` tag. – Seblor Jul 31 '21 at 22:57
  • If I understand what you ask so in componentDidMount remove this.setState({loading: false}); Now you have to options: you can write .then(json => this.setState({data: json, loading: false})); or you can leave it .then(json => this.setState({data: json})); and use componentDidUpdate to check if data has been changed and there to update loading state – elirand5 Jul 31 '21 at 23:09

1 Answers1

2

I think in actual workplace, the way your team decided to use is the best way, so it would be case by case.

But personally, based on your code here I prefer to write like this:

// use React Hooks
import React, { useState, useEffect } from 'react';

// Functional Components
const App = () => {
  const [data, setData] = useState([]);

  // useEffect is pretty much the equivalent of componentDidMount if you pass an empty array as the second argument.
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('Your API Url.');
        const json = await response.json();
        setData(json);
      } catch (error) {
        console.error(error);
      }
    }
    fetchData();
  }, []);

  // Conditional Operator and Optional Chaining to help conditional render.
  return (
    <div>
      { data?.length > 0
        ? <h1>{data[0]['name']}</h1>
        : <div>{`Loading...`}</div>
      }
    </div>
  )
};

export default App;

You could also read more about how to use async await syntax inside useEffect here.

Hope this will help a bit.

Chiyu
  • 21
  • 2