Book Image

Mastering Immutable.js

By : Adam Boduch
Book Image

Mastering Immutable.js

By: Adam Boduch

Overview of this book

Immutable.js is a JavaScript library that will improve the robustness and dependability of your larger JavaScript projects. All aspects of the Immutable.js framework are covered in this book, and common JavaScript situations are examined in a hands-on way so that you gain practical experience using Immutable.js that you can apply across your own JavaScript projects. The key to building robust JavaScript applications using immutability is to control how data flows through your application, and how the side-effects of these flows are managed. Many problems that are difficult to pinpoint in large codebases stem from data that’s been mutated where it shouldn’t have been. With immutable data, you rule out an entire class of bugs. Mastering Immutable.js takes a practical, hands-on approach throughout, and shows you the ins and outs of the Immutable.js framework so that you can confidently build successful and dependable JavaScript projects.
Table of Contents (23 chapters)
Title Page
Credits
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

Unidirectional data flow


React and Flux have popularized the concept of unidirectional data flow as the fundamental concept that drives web application architecture. A unidirectional data flow is exactly what it sounds like—data that flows in one direction. It's a simple idea, but it's an important mindset to adopt when thinking about immutable data.

What other direction is there?

The best way to visualize unidirectional data flow is in a top-down fashion. Data starts in one state at the top, changes state as it flows downward, ending with a side-effect that does something with the data. When this is enforced as a property of the architecture, side-effects are predictable. We can easily trace the starting point of data, through the transformations it makes, ending with the visible side-effect.

When we don't enforce a unidirectional data flow, it's difficult to trace cause and effect. This is the main reason that Facebook started promoting the concept with the creation of Flux—to prevent components from changing state at will and passing the changed state on to another component. For example, let's say that you aren't using immutable data, and that one component changes its state in response to an event. Then some other component that references this state renders itself, causing its state to change as a result of the first change. These are nothing more than uncontrolled side-effects.

Immutable.js is a low-level library compared to the ideas of Flux or a UI component library such as React. Even if you're not using either of these, you can still leverage Immutable.js to build a unidirectional architecture.

Subscriptions are out

One approach to handling data that changes is to observe it. This means using some mechanism to attach a listener callback function that's called whenever the data changes. For example, you could have data that models a user interface component, and when that data changes, you would render the component so that it reflects the changed data.

To set up subscriptions like this will require data that can change, which we don't want. Since we're working with immutable data that never changes, subscriptions are a dead end. This means that you have to rethink your approach for notifying components about the state of your data. The rule of thumb with immutable architectures is that only new data is passed around when things change.

Data is only created

Let's revisit the visualization of data flowing from top to bottom, ending with a side-effect. Along the way, we're either changing the state of data with persistent changes, or we're shaping the data that we need using sequence transformations. From the beginning to the end of this flow, we're only creating new data.

The chained Immutable.js collection method calls result in new data—every time. This means that if we make a mistake and accidentally try to use data in a way that falls outside of the unidirectional flow that we're following, Immutable.js will protect us from ourselves. When this happens, the result is often a broken application that doesn't work. This is better than a half-working application that has mutability bugs hidden deep inside of it.

For example, suppose that we call set() on an immutable map to set a value, expecting that simply calling this method would be enough to change the state of the map. But since the set() method is a persistent change, it doesn't change the map—it creates and returns a new map. So while we weren't expecting this behavior, it's better than accidentally changing the state of something.

Implicit side-effects are hard to do

Side-effects in code that uses mutable data are implicit. Immutable.js, on the other hand, promotes explicit side-effects by placing them at the end of a method call chain. This makes the side-effects in your code easy to spot, and easy to reason our way through the sequence of transformations and persistent changes that lead up to the side-effect occurring.

Implicit side-effects are problematic because we don't have any meaningful way to track them. For example, you change some data that results in four function calls being made. Do any of them have side-effects? Two of them? All of them? Do the side-effects cascade into other side-effects? We're creating too much work for our brains to handle here.

The trick with Immutable.js is to make explicit the things that matter when you're reading code. This means quickly figuring out what caused a given side-effect to occur. On the other hand, you can't make everything explicit otherwise you'd have a mountain of code to sift through. The implicitness of Immutable.js comes with piecing together data by gluing it together using chaining—there's a lot going on behind the scenes that you don't need to think about.