DEV Community

hudson-m-c
hudson-m-c

Posted on

Redux Cheatsheet

This article will lay out the installation, setup, and usage of Redux in a React App. There will also be an overview of reducers, seeing as the Redux store requires one upon creation.

Installation

Install the Redux and React-Redux library in your project's main directory:

npm install redux react-redux
Enter fullscreen mode Exit fullscreen mode

Setup

Below are key imports for Redux and React-Redux's main functionality:


import { createStore } from 'redux';
...
import { Provider } from 'react-redux';
...
import { connect } from 'react-redux'

Enter fullscreen mode Exit fullscreen mode

Inside of your main JS file for rendering your app (i.e. index.js) we need to:

  1. Import our necessary functions and components
  2. Create a store
  3. Implement the Provider component
  4. Render our app

// Standard React imports
import React from 'react';
import ReactDOM from 'react-dom'

// Redux related imports
import { createStore } from 'redux';
import { Provider } from 'react-redux'

// Reducer to manage the store's data
import reducer from './reducer'

// Main application component
import App from './App'


// Create a store for our state
const store = createStore(reducer);


// Render our application
ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>
, document.getElementById('root');

Enter fullscreen mode Exit fullscreen mode

Usage

Understanding

React-Redux allows the developer to connect a React component to a Redux store. This connection needs to define the communication from and to the store.

  • From - state needed for the component as props
  • To - functions that define the intended changes to state (action)

If a component only needs one form of communication, set the other type to null.

Inside of your React component, we need to do three steps to connect:

  1. Import functions that define needed actions
  2. Create a function that defines how state is mapped to props
  3. Connect and export the component

Implementation

Let's say we have an app that handles RSVP'ing to a wedding. One of many requirements would be for a guest to register their dining preference.

To satisfy this requirement, we need some component to:

  • Display a known list of all food preferences
  • Get user input for their preferred food

// necessary non-Redux imports for component
import React from 'react'

// Redux related imports
import { setPreference } from './actions'

const mapStateToProps = ( state ) => {
    return {
        preferences: state.preferences,
        currentGuest: state.currentGuest
    }
};

// React component setup with state as props
const GuestPreference = ( props ) => {
   return (
      <div className='container'>
         <h2>Please set your preference {props.currentGuest.name}</h2>
         {
            props.preferences.map( item => {
               <div onClick={ () => props.setPreference(item) }>
                  { item }
               </div>
            })
         }
      </div>
   )
};

// Export and connect the component to the store
export default connect( mapStateToProps, { setPreference })(GuestPreference)

Enter fullscreen mode Exit fullscreen mode

Reducers

Understanding

A reducer is a function that manages state in a pre-defined way. This is the behavior that allows Redux to be consistent.

When creating a reducer, two things are expected:

  1. The structure of state will be consistent
  2. Interaction with state is defined through an object.

That structure is often referred to as initial state. For example:


const initialState = {
    /* example application state */
    guests: [],
    currentGuest: {
        name: "Stephen",
        ...
        preference: ""
    },
    preferences: ["Steak", "Fish", "Salad"]
}

Enter fullscreen mode Exit fullscreen mode

That object is referred to as an action with a standard structure of:


{
    type: /* String defining how to manage */,
    payload: /* any javascript value */
}

Enter fullscreen mode Exit fullscreen mode

Implementation

Let's stick with the RSVP app idea for consistency. This app has pre-defined behavior of setting the guest's food preference.

As such, we need to create a function that returns an action our reducer can interpret and reliably know what to do with the data. For instance:


/* inside of a file 'actions.js' */

// create and export types for our actions
export const SET_PREFERENCE = "SET_PREFERENCE";

// create functions that return pre-defined actions
export const setPreference = ( name ) => {
    return {
        type: SET_PREFERENCE,
        payload: name
    }
};

Enter fullscreen mode Exit fullscreen mode

Now there is a standard for how our reducer should manage data. Let's create the reducer.


/* inside the file reducer.js */

// import the types this reducer supports
import { SET_PREFERENCE } from './actions'

// create the reducer, please note the javascript shorthand
function reducer(state = initialState, action) {
    // work off of the type
    switch(action.type) {
        // type for setting preference
        case SET_PREFERENCE:
            return {
                // keep the state we don't touch
                ...state, 
                currentGuest: {
                     // keep the nested state of current guest
                    ...state.currentGuest,
                    // set the preference from the action
                    preference: action.payload
                }
            };

        // default statement for types not yet supported
        default:
            return state;
    }
}

// export the reducer
export default reducer;

Enter fullscreen mode Exit fullscreen mode

Please note how the reducer does not directly manipulate the state but rather creates a copy and uses it instead.

Top comments (0)