Fetching with React Hooks

Posted by Arthur on June 19, 2021

So with class components there were a lot of connect method calls & calls to mapStateToProps & mapDispatchToProps along with the layers of indirection like actions and reducers.

With hooks, things are a lot clearer and simpler.

This is the source for a simple project that makes fetch calls via react hooks [source]. This is just the link to the source and some source code but I will elaborate upon the various details soon. This is just a placeholder for elaboration later.

And this is the source code :

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createStore } from 'redux'; // this allows us to create store
import { Provider } from 'react-redux'; 
// we pass the store obj to top level container Provider
import rootReducer from './reducers/rootReducer.js';

const store = createStore(rootReducer);

const rootElement =   document.getElementById('root')
// added Provider to wrap around App
ReactDOM.render(
  <Provider store={store}>
      <App />
  </Provider> ,
  rootElement
);

Before we go into using useEffect to make a fetch call allow me to go over the ouline of the code:

useEffect( fetchdata(),[ empty_array__so_as_to_fetch_only_once] );

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.

The API for useEffect is :

useEffect( () => { . . . return cleanup; },[var_n_whose_change_triggers_useEffect . . .] );

So here is the code which actually makes a call to the backend:

App.js

import './App.css';
import { useSelector, useDispatch } from 'react-redux';
import {  useEffect, useState } from 'react';

import React from 'react';

function App() {
  const [words, setWords] = useState([]);

  let fetchData = () => {
                          fetch('http://localhost:4000/words')
                          .then(response => response.json())
                          .then (data =>
                                            {
                                                  setWords(data);
                                            } 
                                          )
                        };

  useEffect(fetchData, [] );


    return (
    <>
    {
      words.map(w=> <div>{w.word}</div>)
    }
    </>
  );
}

export default App;

The json I am getting from the api is:

[
{
"id": 1,
"word": "abase",
"definition": "Lower ; humiliate.",
"sentence": "Defeated, Queen Zenobia was forced to abase herself before the conquering Romans, who made her march in chains before the emperor in the procession celebrating his triumph.",
"category_id": 1,
"category": {
"name": "3,500 Basic"
}
},
{
"id": 2,
"word": "abash",
"definition": "embarrass.",
"sentence": "He was not at all abashed by her open admiration.",
"category_id": 1,
"category": {
"name": "3,500 Basic"
}
},
{
"id": 3,
"word": "abate",
"definition": "subside; decrease, lessen.",
"sentence": "Rather than leaving immediately, they waited for the storm to abate.",
"category_id": 2,
"category": {
"name": "Hot Prospect"
}
},
{
"id": 4,
"word": "abridge",
"definition": "condense or shorten.",
"sentence": "Because the publishers felt the public wanted a shorter version of War and Peace, they proceeded to abridge the novel.",
"category_id": 3,
"category": {
"name": "High Frequency"
}
}
]