hudson-m-c
Posted on April 16, 2020
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
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'
Inside of your main JS file for rendering your app (i.e. index.js) we need to:
- Import our necessary functions and components
- Create a store
- Implement the Provider component
- 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');
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:
- Import functions that define needed actions
- Create a function that defines how state is mapped to props
- 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)
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:
- The structure of state will be consistent
- 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"]
}
That object is referred to as an action with a standard structure of:
{
type: /* String defining how to manage */,
payload: /* any javascript value */
}
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
}
};
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;
Please note how the reducer does not directly manipulate the state but rather creates a copy and uses it instead.
Posted on April 16, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.