Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
Redux together with React provide one of the most powerful front end setups that you can use nowadays. Using those two libraries as the foundations of your tech stack is an easy decision to make when you are looking for scalability, performance and ease of use.
In the scope of this article we will look into Sagas. A specific way to handle asynchronous side-effects in Redux applications and the benefits we get from them.
When I first started dealing with React and Redux, the best way to handle asynchronous side-effects was using thunks or some promise resolving middleware.
Then I ventured into the world of Observables, which proved themselves as a solid and even more powerful solution that came with the cost of a steeper learning curve.
Somehow the redux-saga library always flew under my radar and I never paid much attention to it. Lately, however, I had the opportunity to work with Sagas and I’m becoming more and more fond of them with each line of code written.
The Saga Pattern
What we’ll talk about does not come from the world of JavaScript. It is a concept in computer science which you can read more about here.
To understand this pattern properly we must first understand transactions. Especially in back-end development they are used whenever we want to execute a series of database operations and revert them all back if one of them fails.
Sagas build up on transactions by setting a few requirements for how they are executed. Each step of the transaction should have a compensating action that should handle its failure.
How is this helpful?
In a simple transaction that consist of a few steps the most likely error handling scenario would be to revert everything. However, in long running transactions there may be cases in which you will want to take different actions depending on the place in which the operation failed.
If the transaction is related to saving data, perhaps you will not want to discard everything if the process fails on the last step. Maybe the essential part is already stored and can be safely used.
The scenarios here are infinite and entirely depend on the business logic of the program you are creating and the area of software development that you are working in.
This talk is a great introduction to the concept in terms of distributed systems.
Front end development and Sagas
The examples I’ve given are only related to server side functionality and database transactions. However, implementing a similar pattern is quite useful on the front-end as well.
Often we need to put the UI in different states depending on the state of the request. Undoubtedly in your Redux apps you have added loading flags which get set to true when the request is pending. You can consider this chain of operations as a transaction.
Once you fire the request the app is put in pending state. Depending on the result you will either see the response of your request or some error message.
The basic example aside, often you will be firing multiple requests and updating multiple pieces of the store where you would be happy to have more control over how you handle errors.
The Sagas of Redux
If you are already sold on trying out such a pattern, redux-saga is the library you are looking for. I strongly believe it’s a solid choice for async side-effect handling in Redux apps.
The problems with asynchronous operations is that they can get hard to read. It can get messy when we pass the threshold of a simple API request and testing becomes a burden.
Sagas alleviate the pain of asynchronous side-effects by letting us write async code synchronously and use try-catch blocks for error handling.
This is achieved with the use of generator functions — a fresh feature that came with ES6. With their help, our flow of operations becomes more easy to read, write and also test. If you are not familiar with the topic I highly recommend this video from the Fun Fun Function channel.
Sagas work like a middleware that have all dispatched actions pass through them. Then they will listen for particular actions and execute operations based on that.
As an example, every time you dispatch a REQUESTING action your sagas will fire the request to the API and dispatch a SUCCESS action if the call is successful.
If the call fails for some reason it will fall into the catch block and the saga will dispatch aFAILÂ action.
For simple situations this may seem a bit confusing, but as the complexity of the flow grows you start feeling the benefit of reading and writing synchronous code. Avoiding highly nested callbacks is key when it comes to code readability.
Sagas are also quite useful when it comes to branching out different requests when some action is dispatched. You can have more than one saga listening for an action making it clear what exactly is happening.
Benefits
This way all request handling logic will be contained in the sagas, leaving your action creators and components clean. If you’ve used thunks you know that action creators, in particular can get quite convoluted.
Writing Sagas is fairly easy and the API of the library is quite intuitive and well documented. Since they are nothing more than generator functions they can be tested thoroughly by asserting what you expect at each step of the saga.
There are also ways to test the flow of the saga without explicitly checking each step by using redux-saga-test-plan.
Conclusion
Sagas are an excellent way to handle async side-effects in a readable and easy to maintain manner. Generators are much easier to learn than Observables and testing tends to get a lot easier.
I am the type of person who is sceptical of new libraries but this one has proven to be a solid choice. I strongly encourage everyone who hasn’t worked with them to go through the tutorial on the redux-saga docs page.
The Sagas of Redux was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.