Fetching data with reactjs

Since the introduction of functional components and hooks in ReactJs, the way that developers handle data fetching has changed. Before that, developers were used to handle code for a given special function that triggers at specific times during the life cycle of the component, for example: beforeMount, componentWillMount, componentMounted and others.

For each of those methods, the ReactJs API was defined and it was the door to hook into the component’s lifecycle.

npx create-react-app fetch-data

Next up, open up the project in your favourite IDE i am going to use web storm:

webstorm . 

Let’s start with fetching data from the Pokemon API, in the App component let’s use state and effect to do that when the component mounts:

// App.jsx
import './App.css';  
import {useEffect, useState} from "react";  
  
function App() {  
  const [pokemons, setPokemons] = useState([]);  
  
  useEffect(() => {  
    fetch('https://pokeapi.co/api/v2/pokemon?limit=10&offset=0')  
        .then(response => response.json())  
        .then(data => setPokemons(data.results));  
  }, []);
  
  return (  
    <div className="App">  
      {pokemons.map(pokemon => <p key={pokemon.name}>{pokemon.name}</p>)}  
    </div>  
  );  
}  
  
export default App;

For this simple scenario, the function App has no dependencies that it needs to be able to trigger the fetch again. This starts to pop out when we start to move fetch into a dependency. Let’s pretend we want to extract the fetch to another file so it can be reused, as follows:

// fetch.js
export const fetchData = async (url) => {  
  const response = await fetch(url);
  const json = await response.json();
  return json.results;  
};

// App.jsx
import './App.css';  
import {useEffect, useState} from "react";  
import { fetchData } from './fetch';
  
function App() {  
  const [pokemons, setPokemons] = useState([]);  
  
  useEffect(() => {  
    fetchData('https://pokeapi.co/api/v2/pokemon?limit=10&offset=0')  
        .then(data => setPokemons(data));  
  }, []);
  
  return (  
    <div className="App">  
      {pokemons.map(pokemon => <p key={pokemon.name}>{pokemon.name}</p>)}  
    </div>  
  );  
}  
  
export default App;

What are the dependencies anyway?

React uses dependencies to sync the external state with the internal state of a component. That way, react knows when something has changed outside of its scope and reacts to it. The official documentation documentation categorizes three types of dependencies of a component:

  • Empty array
  • Dependencies with array
  • No dependencies

How to avoid unnecessary rerenders?

  • Avoid unnecessary re-renders in ReactJS
  • How to fetch data with React Hooks
    • this tutorial has exactly example of nasty loop
  • In the course Reactjs Masterclass from Shubham Sarda he depicts a scenario in which a changing url should trigger a api call to an endpoint, when he does that, the app enters on a infinite loop, because useEffect cannot determine if a function as changed or not (even though the linter says to add the fetch function inside the dependency array), the following picture depicts the issue:
    • the fix is simply adding the useCallback hook
    • In another video, the author also uses useRef to prevent rerendering, this time, useRef is used because the body is an object and this object is passed as a reference to a custom hook:

Resources