When developing a React frontend with data frequently being fetched from a backend/API, it can sometimes become challenging passing state through props from one component to the next. This practice can be very tedious and can tempt you to fetch data from a less-than-ideal component just to simplify the state issue.
Redux is a state manager that allows you to store and retrieve data from any component on your front-end. I'm going to go through the process of setting up Redux in your app.
First, you will need to install the redux library. Run both of the following commands:
yarn add redux
yarn add react-redux
Next, we will create a reducer. A reducer accepts two arguments: current state & an action (e.g. user logged in/out, data fetched, auth failed). The new updated state will be returned by the reducer, taking into account the action that was passed to it.
Here is an example of a reducer (I would create this reducer in a separate file; let's call this file 'auth-reducer'):
const INITIAL_STATE = {
email: '',
password: '',
auth_token: '',
errorFlag: false,
spinner: false
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'EMAIL_CHANGED':
return { ...state, email: action.payload };
case 'PASSWORD_CHANGED':
return { ...state, password: action.payload };
case 'LOGIN_FAILED':
return { ...state, errorFlag: true, password: '', spinner: false };
case 'LOGIN_USER_SUCCESS':
return { ...state, ...action.payload, spinner: false };
case 'FIND_USER_SUCCESS':
return { ...state, ...action.payload, spinner: false };
case 'LOAD_SPINNER':
return { ...state, spinner: true };
case 'LOGOUT_USER_SUCCESS':
return INITIAL_STATE;
default:
return state;
}
};
Next, we'll create a Redux store in our app component. First we need to import several items.
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import AuthReducer from './AuthReducer'
-> (this is where we created our reducer in the last step)
Now we are ready to create our Redux store.
const store = createStore(AuthReducer);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById(‘root’)
);
Notice that we created a store using the createStore function and passed it our AuthReducer. I also wrapped the 'App' component in a 'Provider' component which will allow all components inside App to access our store.
To access state inside a component you will create a function that assigns redux's state to the component's props. This is how I implemented my AuthReducer inside a login componenet:
const mapStateToProps = (state) => {
return {
email: state.auth.email,
password: state.auth.password,
error: state.auth.errorFlag,
spinner: state.auth.spinner,
auth_token: state.auth.auth_token
};
};
At the bottom of my component I also need to specify that I am using this functionality.
export default connect(mapStateToProps)(LoginForm);
Inside that component I could then access the password attribute in redux's state, by calling this.props.password
.
To update redux's state you can either use mapDispatchToProps function or create individual actions that modify state. I will explain the process of creating individual actions.
If I wanted to change a user's email and/or password in state I could add the following functions:
export const emailChanged = (email) => {
return {
type: 'EMAIL_CHANGED',
payload: email
};
};
export const passwordChanged = (password) => {
return {
type: 'PASSWORD_CHANGED',
payload: password
};
};
Now, inside my auth component I would import these functions and call them by passing in a new email/password. I would also need to modify my final export statement to the following:
export default connect(mapStateToProps, { emailChanged, passwordChanged })(LoginForm);
This run through should allow you to quickly set up a React App with Redux. There are many powerful ways to utilize Redux to improve performance and organization so I hope you enjoy. Check out the links below for further questions.
Sources:
1. Redux Docs
2. React-Redux Docs
3. Quick and easy beginner’s guide to implementing Redux in a React app, by Paul Fitzgerald
Top comments (0)