React Hooks and Fetch
Tags: javascript, beginners, react, tutorial
Published: 2021-12-06 15:51:25

This blog will be detailing how to use React Hooks with Fetch to get data.

_"Note that all React packages need to be 16.8.0 or higher to enable Hooks. Hooks won't work if you forget to update"._

## Backend

Let's first look at the database I used for this demonstration. I used a rails API, but we won't be getting any deeper than this; all you need to know are the attributes that are set up in the table to understand the examples.

```javascript
  create_table "projects", force: :cascade do |t|
    t.string "title"
    t.string "description"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end
```
This code snippet shows a table called "Projects" that has 2 attributes "Title" and "Description". 

---

## Frontend

#### Project Display Component

Displayed is the "project display functional component". The goal. heere. is to  have this component fetch all the projects from my backend so that it can be displayed. 

Let's first take a look at the "imports"

```javascript
import { useEffect } from 'react';
import { fetchProjects } from './projectAction';
import { useSelector, useDispatch } from 'react-redux'

```

1. `useEfect` is similar to `componentDidMount()` which runs additional code before React has updated the DOM. This is important because we want to get our data before the page loads. No data means no projects can be displayed on the DOM. How do we get our data? Yes, Fetch!
This is where the fetch request is happening. 

2. `fetchProjects` is a functional component I created just to handle get request. 

3. `useDispatch` is similar to `connect`. `useDispatch` is React Hooks' way to trigger a state change.

4. `useSelector` is similar to how we would call "this.props.projects" to get data from the redux store; now we have `useSelector`.

### Putting It All Together

##### Project Display Component Functions and Declarations

```javascript
export default function ProjectDisplay() {

  const projects = useSelector(state => state.projects)
  const dispatch = useDispatch()
 
  useEffect(() => {
    dispatch(fetchProjects())
  }, [])
}
```

1. `const` declaration of "projects" is the return value of `useSelector`. How you set up your reducer(s) and store reflects how you call your state. Typically if  you only passed in 1 reducer component in my redux store, you would just use `const projects =useSelector(state => state)`, but I passed in a `combineReducer`,  which like it says, combines all the different reducer components,  so you have to specify which one you want. How the `Store` looks like ... 

```javascript
import { applyMiddleware, createStore, combineReducers } from "redux";

import thunk from "redux-thunk"
import userReducer from "./reducers/userReducer";
import projecReducer from "./reducers/projectReducer"
import taskReducer from "./reducers/taskReducer"


let rootReducer = combineReducers({user: userReducer, projects: projecReducer, tasks:taskReducer  })

export default createStore(rootReducer, applyMiddleware(thunk))

```

2.`const` declaration of "dispatch" gives us access to the usDispatch function by just calling Dispatch

3. `useEffect` takes in 2 arguments. The first argument takes in a function.  In this example, we created a call-back function with `dispatch` to trigger a change in`state`. Then in our function dispatch we call on our `fetch` function (fetchProject). The second argument in `useEffect` takes in an array of dependencies. In this example, we have none, so we left the array empty.

##### Fetch Function (fetchProject)

You should already be familiar with how to write a `fetch` function, so I will only be getting into how it changes our `state`. 

```javascript
export function fetchProjects(){
    return dispatch => {
        fetch('http://localhost:3000/projects')
        .then(r => r.json())
        .then( projects => { 
           
            dispatch({type:"SET_PROJECTS", payload: projects})})
    }
}

```

1. What is fetch doing? Fetch is  going to the url provided, in this case the route of my backend and 'GET'/getting all the projects. 

2. The new addition to this fetch request is `dispatch({type:SET_PROJECTS, payload: projects}`. In the second `promise` of our function. We call `dispatch` to change the state, which we still need to do within the fetch request. `dispatch` takes in an `action`, an object that describes what happened (`{type:SET_PROJECTS, payload: projects}`). `type` is a string used to match  our `case` in the `switch` statement (located in the reducer which changes our store's `state`). `payload` in this example is the data retrieved.


##### Change state with Reducers

Remember that we are passing in reducers to our redux store,  so to change our `state` inside of our store, we must modify the information in our reducers. After the fetch request, the second dispatch accesses the reducer. 

This is the Project Reducer:

```javascript
export default function projectReducer(state=[], action) {
    switch(action.type){
        case "SET_PROJECTS":
           
            return action.payload; 
    }
}

```
1. The project reducer takes in 2 arguments. 1. the state,  which is being defaulted to an empty array,  and 2.  action, which is what refers to the object that was sent through dispatch (`dispatch({type:SET_PROJECTS, payload: projects}`).

2.With `switch` the value of the expression (action.type) is compared with the values of each case. in this example, we used action.type,  which renders out to be "SET_PROJECTS" because it is what was passed through in our `dispatch`. In the case statement, we are returning the state. By calling action.payload  the state is snow equal to the data we got from our fetch,  which is an array of  Project objects .


##### Back to Project Display Component to render


```javascript
const projects = useSelector(state => state.projects)
```
Now that our `state` is an array of project objects We can render them in our DOM. remember our  `useSelector` function declared earlier in the project component? We can use the const project like this ...

```javascript
return(
 <div>
            <h1>Projects</h1>
            <ul>
            
                {projects.map(p =>{
                return(
                    <li key={p.id}>
                        
                        
                        <p>{p.description}</p>
                        <p>{p. completion_rate}</p>
                        <button onClick={()=>{handleClick({p})}}>Delete</button>
                             
                    </li>
                )})}
            </ul>
        </div>             
)
```
As you can see we are mapping through projects and displaying each project in an unordered list on the DOM.