Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add update() docs #1155

Merged
merged 1 commit into from
Feb 21, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/_data/nav_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
title: Test Utilities
- id: clone-with-props
title: Cloning Components
- id: update
title: Immutability Helpers
- id: examples
title: Examples
- title: Reference
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/09-addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ next: animation.html

- [`ReactTransitions`](animation.html), for dealing with animations and transitions that are usually not simple to implement, such as before a component's removal.
- [`ReactLink`](two-way-binding-helpers.html), to simplify the coordination between user's form input data and and the component's state.
- [`classSet`](class-name-manipulation.html), for manipulating the DOM `class` string a bit more cleanly.
- [`classSet()`](class-name-manipulation.html), for manipulating the DOM `class` string a bit more cleanly.
- [`ReactTestUtils`](test-utils.html), simple helpers for writing test cases (unminified build only).
- [`cloneWithProps()`](clone-with-props.html), to make shallow copies of React components and change their props.
- [`update()`](update.html), a helper function that makes dealing with immutable data in JavaScript easier.

To get the add-ons, use `react-with-addons.js` (and its minified counterpart) rather than the common `react.js`.
2 changes: 1 addition & 1 deletion docs/docs/09.5-clone-with-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Cloning Components
layout: docs
permalink: clone-with-props.html
prev: test-utils.html
next: examples.html
next: update.html
---

In rare situations a component may want to change the props of a component that it doesn't own (like changing the `className` of a component passed as `this.props.children`). Other times it may want to make multiple copies of a component passed to it. `cloneWithProps()` makes this possible.
Expand Down
63 changes: 63 additions & 0 deletions docs/docs/09.6-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
id: update
title: Immutability Helpers
layout: docs
permalink: update.html
prev: clone-with-props.html
next: examples.html
---

React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it's easy to implement a fast `shouldComponentUpdate()` method to significantly speed up your app.

Dealing with immutable data in JavaScript is more difficult than in languages designed for it, like [Clojure](http://clojure.org/). However, we've provided a simple immutability helper, `update()`, that makes dealing with this type of data much easier, *without* fundamentally changing how your data is represented.

## The main idea

If you mutate data like this:

```javascript
myData.x.y.z = 7;
myData.a.b.push(9);
```

you have no way of determining which data has changed since the previous copy is destroyed. Instead, you need to create a new copy of `myData` and change only the parts of it that need to be changed. Then you can compare the old copy of `myData` with the new one in `shouldComponentUpdate()` using triple-equals:

```javascript
var newData = deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
```

Unfortunately, deep copies are expensive, and sometimes impossible. You can alleviate this by only copying objects that need to be changed and by reusing the objects that haven't changed. Unfortunately, in today's JavaScript this can be cumbersome:

```javascript
var newData = extend(myData, {
x: extend(myData.x, {
y: extend(myData.x.y, {z: 7}),
}),
a: extend(myData.a, {b: myData.a.b.concat(9)})
});
```

While this is fairly performant (since it only shallow copies `log n` objects and reuses the rest), it's a big pain to write. Look at all the repetition! This is not only annoying, but also provides a large surface area for bugs.

`update() provides simple syntactic sugar around this pattern to make writing this code easier. This code becomes:

```javascript
var newData = React.addons.update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [7]}}
});
```

While the syntax takes a little getting used to (though it's inspired by [MongoDB's query language](http://docs.mongodb.org/manual/core/crud-introduction/#query)) there's no redundancy, it's statically analyzable and it's not much more typing than the mutative version.

The `$`-prefixed keys are called *directives*. The data structure they are "mutating" is called the *target*.

## Available directives

* `{$push: array}` `push()` all the items in `array` on the target
* `{$unshift: array}` `unshift()` all the items in `array` on the target
* `{$splice: array of arrays}` for each item in `array()` call `splice()` on the target with the parameters provided by the item.
* `{$set: any}` replace the target entirely
* `{$merge: object}` merge the keys of `object` with the target