Notes

Using Redux with React

Edit on GitHub

Redux
4 minutes

The plan:

  • Create a race condition to justify the use of Redux and Redux Saga
  • Learn Redux and React-Saga along the way

NOTES:

You can not make API calls and routing transitions inside a reducer

This! This basically means you are bound to use some third party library to handle updating state with data returned by the API calls, hello middleware! You must use something like redux-thunk or redux-saga, there is no two ways about it. Because:

  • i can’t imagine a React app that doesn’t make an API call. React is just the View. The data always comes in from somewhere else.
  • we can’t make API calls in reducers, and reducers update state..
  • State is an {}
  • Action is an {}
  • Reducer is a pure function ()
  • Redux will only give you global state that is still local. It will not persist. You refresh the browser and the state is gone

Redux with React

1npm i redux react-redux @types/react-redux

This is all you need to do in order to get started

  1. Create a store
  2. Create a reducer
  3. Wrap your App in a <Provider> component to be able to access the store from anywhere in the app
 1import React from 'react'
 2import ReactDOM from 'react-dom'
 3import App from './App'
 4import { createStore } from 'redux'
 5import { Provider } from 'react-redux'
 6
 7const rootReducer = (state = {}, action: {}) => {
 8  return state
 9}
10
11const store = createStore(rootReducer)
12
13ReactDOM.render(
14  <Provider store={store}>
15    <App />
16  </Provider>,
17  document.getElementById('root')
18)

You need to do the following setup once in order to use Redux inside your react app

Create a global store

We need createStore() from redux in order to cerate a store.

1import { createStore } from 'redux`
2
3const store = createStore(reducer, preLoadedState) // optional third arg is middleware (say sagas or thunk)

Create a reducer. We need at least one to get started

(previousState, action) => newState

The reducer is a pure function that takes the previous state and an action, and returns the next state.

1const reducer = (state = {}, action: {}) => {
2  return state
3}

Use the store inside the App

Then we’ll use the <Provider> component and wrap our entire app inside it. This will make the entire app (i.e. wherever we want to use values from the store) be able to access the store. <Provider> will take a store property.

1ReactDOM.render(
2  <Provider store={store}>
3    <App />
4  </Provider>,
5  document.getElementById('root')
6)

Actions

Actions are what tell you what to change in state. The reducer will then change the state based on whatever action was given. You can either write an if statement or a switch. Convention is to use switch cases.

1const rootReducer = (state = {}, action: {}) => {
2  return state
3}

will become

 1const rootReducer = (state = initialState, action: { type: string }) => {
 2  switch (action.type) {
 3    case 'INCREMENT':
 4      // do something
 5      return { count: state.count + 1 }
 6    case 'DECREMENT':
 7      // do something
 8      return { count: state.count - 1 }
 9    default:
10      return state
11  }
12}

Action is just an object. type is by convention, you can call it whatever, and it doesn’t necessarily have to be a string, but that’s also convention.

Use stuff from the store

Now comes the fun part, and the part that Redux has improved on, managing the state using hooks

  • useDispatch() - dispatch an action
  • useSelector() - selects relevant parts of the state object, takes a callback
1const count = useSelector((state: any) => state.counter) // this will give you just the `count` property from the state
2const dispatch = useDispatch() // this will let you send actions
3
4dispatch({ type: 'DECREMENT' })

Action is an object. So whenever you dispatch actions, you’d have to give dispatch() an action object (with the type that we are expecting)