Skip to content
Tyler Faux edited this page Sep 13, 2016 · 2 revisions

Tide is our lightweight library for working with immutable data inside a React app. It follows some of the ideas used in Flux, but gets rid of the central dispatcher and multiple store structure.

Like in Flux the majority of your app logic is kept outside of your views, and the data flows unidirectionally. There is however only one store - the global state object - that contains the state of your entire app inside an Immutable data structure.

+--------------+                        +-------+
| Global state | ---------------------> | Views |
+--------------+                        +-------+
       Ʌ                                    |
       |                                    |
       |            +---------+             |
       +----------- | Actions | <-----------+
                    +---------+    

Your views call methods in your Actions, which are responsible for writing to the global state object. A change in the global state triggers an event propagated to all views reading from it, and the views then determine if they need to re-render or not. Working with immutable data allows us to easily and efficiently check for changes in the data, as explained in the section below.

Immutable Data

The main reason for using immutable data in the global state is that it becomes very easy and efficient to check for when the data has changed. Instead of running deep, nested comparisons in objects, we can simply compare object identities to know if they hold the same data (foo === bar). This means that we no longer need to structure our app into a hierarchy of controller views, but let each view decide by themselves if they need to re-render each time we change the global state.

We use Facebook's Immutable library to work with immutable data in JavaScript. Here's an example of it in use:

const store = Immutable.fromJS([
  { name: 'Alice', age: 32 },
  { name: 'Bob', age: 36 },
])

const alice = store.get(0)
const bob = store.get(1)

// It's Bob's birthday, and now he's 37!
const updatedStore = store.updateIn([1, 'age'], (age) => age + 1)

const updatedAlice = updatedStore.get(0)
const updatedBob = updatedStore.get(1)

assert(store !== updatedStore)  // Store has changed
assert(bob !== updatedBob)      // Bob is older and not the same
assert(alice === updatedAlice)  // Alice is still the same

If we were to have one view rendering Alice and another view rendering Bob in the case above, we'd only have to re-render Bob's view on his birthday. Alice's view remains untouched since the data is unchanged and the object identity stays the same.

Further Reading

Clone this wiki locally