Everything Redux — Part 2

Francisco Leal
Runtime Revolution
Published in
6 min readJul 12, 2018

--

This series of posts aims to show how redux works and the different possibilities that it can bring to your application.

Photo by Riccardo Annandale on Unsplash

In my previous post I talked about actions, reducers, the store and selectors, and the core principles of redux. In this post, we’re going to take it to the next level and have a look into side effects and the different options available for your application.

Side Effects

Redux is cool and useful because of the simplicity and cleanliness it brings to your application, but as state becomes more and more complex, with more information, more actions, regular tools start to become lacklustre. Redux isn’t helping us with fetching data, or with delaying code execution, something that most web applications do nowadays with notifications (a bit too much..) and that means that our state isn’t as predictable as we expect it to be.

Vanilla style 🍦

Before jumping on side effects libraries, let’s see how we’d handle fetching information via a vanilla approach such as using the fetch API.

Using fetch() we can simply use the Promise success or rejection in order to trigger our normal redux actions.

This line of thought is already good enough for simple use cases but you will end up with duplicate code in a lot of places and it will soon turn into callback hell as more and more functionalities are added. For me to demonstrate the thought process behind side-effects and how we can apply them let’s imagine a situation where we want to show a series of modals to the user. We have a modal that is controlled via our state and we have a Show / Hide action that keeps the state consistent.

We don’t want to duplicate code, therefore we use this logic as a Modal management system. When we start having different parts of our application using it we’ll have the need to add an identifier to our modal so that we’re not dispatching hideModal() actions and hiding the modals from somewhere else forcing us to have some logic that manages the ids and dispatches both show and hide actions.

Now you might notice that it is a nuisance that we have to pass around store.dispatch every time that we want to dispatch other actions from within our flow, another issue is that showTemporaryModal is no longer an action we can dispatch and therefore we have to be extra careful and keep in mind that showModal is indeed an action that you dispatch but showTemporaryModal isn’t… now imagine having over 10, 100, 1000 actions in your application and most of those using helpers like showTemporaryModal. It just contributes to having more error prone code and increasing the time we take to build new features and add more logic.

Middleware to the rescue!

This is the point where middleware libraries for side-effects come into view. They handle having dispatch and the store’s state available to you so you don’t have to worry and they also help Redux recognise these helper functions as actions themselves. The most straight forward library for this is Redux Thunk.

Thunks

Redux Thunk simply allows actions to be functions. Here’s the example above using redux thunk.

Now everything is an action and we can dispatch it from anywhere in our application. In the first case of dispatching showTemporaryModal, thunk middleware will take care of passing dispatch as an argument for you and the same goes for the current store state. Here’s how you can access the store state.

We now have everything we need to keep our state transitions in sync with our actions, but personally I find that redux thunk doesn’t do enough when we have the need to include business logic on our action creators and have decoupled workflows when navigating our side effects. Don’t get me wrong, you can do almost anything through redux thunk, but I don’t think it’s the best tool to orchestrate the state machine that redux is.

One step further — Sagas & Observables

There are several options that you can consider if you need to get more out of your redux middleware for side-effects. Sagas (one of the communities favourite with over 14,000 stars on github)and Observables (my personal favourite with ~5,500 stars on github) are two of those.

Now, both of these libraries are fairly complex, and different from one another but there are some concepts that are similar. I’ll do my best to give you a sneak peak of what they are and show an example for each of them.

Sagas make use of es6 generators. Observables make use of.. observables!

In both cases you can look at them as creating a single flow through a sequence of side-effects. Observables do this through Epics which are functions that take a stream of actions and returns a stream of actions. Sagas are similar to what your code would look like if you used async / wait but with some extra functionalities, making asynchronous code look synchronous.

In other words, both Sagas and Observables associate the side-effect with the actions themselves. What does this mean? It means that you take the actions that you have using regular Redux and “attach” a side-effect to it. For Observables, a stream of all actions are created and you can add listeners to this stream and take action on what you see there. In the case of Sagas you add a function that you want to run when a certain action occurs. As a short example I’ll show you how we could take our modal example and track how it’s been used and who’s seeing it (a small logging/analytics example).

And through Observables:

Both of these approaches are extremely clean and easy to build on. Is your logging system getting flooded with requests? Adding a debounce is as simple as:

Take a look at the official documentation for the different operators that you have available:

They might seem like a lot of operators and understanding when and how to use them is not easy, so I’d advise you to look into them before choosing one to add to your project. Here’s a list of some resources that you may find interesting:

  • egghead.io: Very up to date with a lot of information regarding Redux, Observables and Sagas by industry pros.
  • Observables Tutorial: from RxJS team’s Lead Developer
  • Observables Patterns: For angular but you can adapt them to React and wherever you are using them.
  • Sagas Tutorial: Very informative and will also point you to more specific resources
  • Sagas Patterns: talks about the most common operators and how to do error handling

Conclusion

Redux is an awesome tool and by itself can be enough for some of your needs, but if you need complex interactions then take a look into the different side-effects libraries and pick the one that best suits you. Redux Thunk is very easy to use and is powerful enough by itself to suit an application, allowing you to reuse code and keep your code well structured. However it starts to break down when very complex business logic is required. Sagas and Observables shine here, and they both have the same mindset behind how they operate. I tend to prefer Observables over Sagas for the simple reason that I find Observable code to be more readable and easier to understand.

This is it for part II! It’s hard to dive deep into observables or sagas while keeping it short, but hopefully this series has allowed you to understand what redux is and the limitless possibilities it can bring to state management in your application.

I love building products and I found my place to do so at Runtime-Revolution. If you are interested in who we are and what we do, make sure to reach out!

--

--