React Redux-Saga Actions - Step By Step

In my adventures with React redux-saga, I've had to repeat the same process to create a new action, and there were a few occasions where I fumbled -- either I missed a step or did something out of sequence. As a result, I documented the process, step by step, so that in the future I don't waste time. I even created a small application to validate my instructions.

I learned React with Redux-Saga in the Complete React Developer in 2020 Course on Udemy. I highly recommend this course. (Note: Udemy usually has Flash sales for their courses that bring them all to under $20. This one is totally worth the investment.)

To explain the process of creating a new reux-saga action, I will use a specific feature - the order search feature. It has a few parts:
  • Upon a user's sign in, the user's orders will be fetched and presented.
  • When a user signs out, the list of orders is reset.
  • An admin can search for orders by a user's email.

Note: If you want to skip this explanation below and just go straight to the working code, you can visit the repository on Github. You can also visit the working site here to see these features in action. Just remember to open the browser's console to see the actions being executed.


System Setup/Requirements

The database or authentication scheme is irrelevant. In fact, for this small app, the sign in "process" just sets a variable to an email address, and the sign out "process" sets the same variable to null. These processes can be replaced with whatever implementation you choose. For this example, we will only focus on the redux-saga implementation of the order search feature.

The following packages are required for this setup:
  • react-redux
  • redux
  • redux-logger (To log actions to your browser's console)
  • redux-saga
  • reselect

Note: If you haven't installed redux-saga yet, I suggest you refer to the Beginner's Tutorial or to the Udemy class I mention above before proceeding.

For this example, we will create the user saga in the .../src/redux/user folder. If this is your first reducer/saga, create all the files listed below and I will explain them later.
  • /src/redux/user/user.actions.js
  • /src/redux/user/user.reducer.js
  • /src/redux/user/user.sagas.js
  • /src/redux/user/user.types.js
  • /src/redux/user/user.selectors.js
  • /src/redux/root-reducer.js
  • /src/redux/root-saga.js
  • /src/redux/store.js


Now, that you're all set, let's get on with implementing this new action.

1. Define Action Call Constants

Add new actions constant that will control the start, success and failure calls in redux-saga. These values will be referenced in the other files we created. Because we are focusing on the order search feature, and because we don't have a real authentication process set up for this app, we will not list START, SUCCESS, or FAILURE for the sign in or sign out feature. In a real production environment with real authentication, we definitely want a START, SUCCESS, FAILURE action call, but for now we will focus solely on the FETCH_ORDER_* actions.

In the user.types.js file, you would add the following code:


2. Create New Action Call Functions

Add the new set of actions calls for each new action type listed above. These will be called from the front end or wherever you want to trigger the action. Set the payload appropriate for each action, though it can be left null. (The "payload" is a value you need to process the request.)

In the user.actions.js file you would add the following code:


3. Add Variables And Set The State Accordingly

Add code that will return the appropriate payload upon the success or failure of the action. In this case, if the order search is successful, the payload is the list of orders which will be set to the orderHistory variable. If the search fails or if the user signs out, that same variable is set to null.

Note: A failed order search is a systemic failure, like a failed db connection or internet connection. A search that returns 0 results is still a successful search.

In the user-reducer.js file, you would add the following code:


4. Add Selector For New Variables

Add a selector to access each variable from the front end. You can add additional selectors if necessary. For example, if you want to select a single order in the orderHistory list, you can add a selector that would execute a find() upon that list instead of returning the entire list to the front end and executing the find there.

In the user.selectors.js file, you would add the following code:


5. Create Fetch Logic & Add Saga Listeners

Create the function fetchUserOrders() to actually execute the search. For this example, the search is a query upon a json file with order data. It can be any db implementation.

For redux-saga to control its flow, the function needs to be a generator, with "yield put()" calls to the new success and failure action functions at the end of the try and catch blocks respectively. This tells redux-saga to execute the next action.

Note: All asynchronous calls should be yielded as well.

You will also setup listeners for this new function. The onFetchUserOrdersStart() function returns an object that tells redux-sagas to execute fetchUserOrders() when the FETCH_ORDERS_START action is called. The onSignInSuccessFetchOrders() function tells redux-saga to execute fetchUserOrders() when the USER_SIGN_IN action is called.

Lastly, these configurations have to be added to the userSagas() list at the end.

In the user.sagas.js file, you would add the following code:


6. Add New Redux-Saga to master set.

Add the userSagas() array that you created in the user.sagas.js file to the root-sagas.js file. This is included in the store.js file that you will see later.


7. Add New reducer to reducer configuration.

Add the new userReducer you created to the root-reducer.js file. The root-reducer.js file is also included in the store.js file that you will see later.


8. The store.js file.

If you already have the root-reducer.js and root-saga.js files configured for your store, there are NO changes to store.js. But if this is all new, you will need the code below in the store.js file. This is a one-time configuration for redux-saga.


9. Add Font-end Code

In case this is your first reducer or saga implementation, make sure you make the new store available in your application. This is done in the index.js file, or whatever file you use as an entry point in your application.


Below is an example of how you would include the new action in a front-end component. The mapStateToProps() function returns objects that will be pulled from the store and placed into the component's props. The mapDispatchToProps() function assigns a redux-saga action function to a variable that will be available via the component's props.

Note: The full jsx code is omitted below to add clarity to the implementation.


To see this code live, you can visit the app here. You can see the execution of the actions in the console.

You can clone the repository on Github. If you clone it, just remember to execute yarn to update your react project with the specified packages.

Remember, there is no database or actual authentication happening, but the idea is all the same.

Enjoy!

Comments

Popular posts from this blog

Control Blogger's Contempo Theme Background Behavior

Deploying React Apps to GitHub Pages

Hosting React Projects on Heroku