Skip to content

Commit d95249b

Browse files
spenmxstbr
authored andcommitted
feat(docs): Update ImmutableJS docs for grammar and add more reference links to ImmutableJS docs (react-boilerplate#1126)
1 parent c1551f6 commit d95249b

File tree

1 file changed

+44
-17
lines changed

1 file changed

+44
-17
lines changed

Diff for: docs/js/immutablejs.md

+44-17
Original file line numberDiff line numberDiff line change
@@ -11,66 +11,93 @@ for a good explanation of the more intricate benefits it has.
1111

1212
In our reducers, we make the initial state an immutable data structure with the
1313
`fromJS` function. We pass it an object or an array, and it takes care of
14-
converting it to a compatible one. (Note: the conversion is performed deeply so
15-
that even arbitrarily nested arrays/objects are immutable stuctures too!)
14+
converting it to a immutable data structure. (Note: the conversion is performed deeply so
15+
that even arbitrarily nested arrays/objects are immutable structures too!)
1616

1717
```JS
1818
import { fromJS } from 'immutable';
1919

2020
const initialState = fromJS({
21-
myData: 'Hello World!',
21+
myData: {
22+
message: 'Hello World!'
23+
},
2224
});
2325
```
2426

25-
To react to an incoming actions our reducers can use the `.set` and the `.setIn`
26-
functions.
27+
28+
29+
When a reducer is subscribed to an action and needs to return the new state they can do so by using setter methods such as [`.set`](https://facebook.github.io/immutable-js/docs/#/Map/set) and [`.update`](https://facebook.github.io/immutable-js/docs/#/Map/update) and [`.merge`](https://facebook.github.io/immutable-js/docs/#/Map/merge).
30+
If the changing state data is nested, we can utilize the 'deep' versions of these setters: [`.setIn`](https://facebook.github.io/immutable-js/docs/#/Map/setIn) and [`.updateIn`](https://facebook.github.io/immutable-js/docs/#/Map/updateIn), [`.mergeIn`](https://facebook.github.io/immutable-js/docs/#/Map/mergeIn).
2731

2832
```JS
29-
import { SOME_ACTION } from './actions';
33+
import { SOME_ACTION, SOME_OTHER_ACTION } from './actions';
3034

3135
// […]
3236

3337
function myReducer(state = initialState, action) {
3438
switch (action.type) {
3539
case SOME_ACTION:
3640
return state.set('myData', action.payload);
41+
case SOME_OTHER_ACTION:
42+
return state.setIn(['myData', 'message'], action.payload);
3743
default:
3844
return state;
3945
}
4046
}
4147
```
4248

4349
We use [`reselect`](./reselect.md) to efficiently cache our computed application
44-
state. Since that state is now immutable, we need to use the `.get` and `.getIn`
50+
state. Since that state is now immutable, we need to use the [`.get`](https://facebook.github.io/immutable-js/docs/#/Iterable/get) and [`.getIn`](https://facebook.github.io/immutable-js/docs/#/Iterable/getIn)
4551
functions to select the part we want.
4652

4753
```JS
4854
const myDataSelector = (state) => state.get('myData');
55+
const messageSelector = (state) => state.getIn(['myData', 'message']);
4956

5057
export default myDataSelector;
5158
```
5259

5360
To learn more, check out [`reselect.md`](reselect.md)!
5461

55-
## Advanced Usage
56-
57-
ImmutableJS provide many immutable structures like `Map`, `Set` and `List`. But the downside to using ImmutableJS data structures is that they are not normal JavaScript data structures.
62+
## Immutable Records
5863

59-
That means you must use getters to access properties : for instance you'll do `map.get("property")` instead of `map.property`, and `array.get(0)` instead of `array[0]`. It's not natural and your code becoming bigger, you finish by not knowing anymore if you are working with a JavaScript object or an Immutable one. While it's possible to be clear where you are using immutable objects, you still pass them through the system into places where it's not clear. This makes reasoning about functions harder.
64+
ImmutableJS provides a number of immutable structures such as [`Map`](https://facebook.github.io/immutable-js/docs/#/Map), [`Set`](https://facebook.github.io/immutable-js/docs/#/Set) and [`List`](https://facebook.github.io/immutable-js/docs/#/List).
65+
One drawback to these structures is that properties must be accessed via the getter methods (`.get` or `.getIn`) and cannot be accessed with dot notation as they would in a plain javascript object.
66+
For instance you'll write `map.get('property')` instead of `object.property`, and `list.get(0)` instead of `array[0]`.
67+
This can make your code a little harder to follow and requires you to be extra cautious when passing arguments or props to functions or components that try to access values with regular dot notation.
68+
ImmutableJS's [`Record`](https://facebook.github.io/immutable-js/docs/#/Record) structure offers a solution to this issue.
6069

61-
The `Record` structure tries to get rid of this drawback. `Record` is like a `Map` whose shape is fixed : you can't later add a new property after the record is created. The benefit of `Record` is that you can now, along with others .get, .set and .merge methods, use the dot notation to access properties, which is a good point to write simpler code.
70+
A `Record` is similar to a `Map` but has a fixed shape, meaning it's property keys are predefined and you can't later add a new property after the record is created. Attempting to set new properties will cause an error.
71+
One benefit of `Record` is that you can now, along with other immutable read methods (.get, .set, .merge and so on), use the dot notation to access properties.
6272

63-
The creation of a record is less simple. You got to first create the `Record` shape. With the example above, to create your initial state, you'll write :
73+
The creation of a record is less simple than simply calling `.toJS()`.
74+
First, you have to define the `Record` shape. With the example above, to create your initial state, you'll write:
6475

6576
```JS
66-
//the shape
77+
// Defining the shape
6778
const StateRecord = Record({
68-
myData: 'Hello World!',
79+
myData: {
80+
message: 'Hello World!'
81+
}
6982
});
7083

7184
const initialState = new StateRecord({}); // initialState is now a new StateRecord instance
72-
// initialized with myData set by default as 'Hello World!'
85+
// initialized with myData.message set by default as 'Hello World!'
7386
```
7487

75-
Now, if you want to access `myData`, you can just write `state.myData` in your reducer code.
88+
Now, if you want to access `myData`, you can just write `state.myData` in your reducer code and to access the `message` property you can write `state.myData.message` as you would in a plain javascript object.
89+
90+
### Gotchas of Using Records
91+
92+
Although dot notation can now be used to read properties the same does not apply to setting properties. Any attempts to set a property on a `Record` using dot notation will result in errors.
93+
Instead setter methods ( `.set`, `.update`, `.merge`) should be used.
94+
95+
Certain properties can not be set on a record as they would conflict with the API. Consider the below example:
96+
```JS
97+
const ProductRecord = Record({
98+
type: 'tshirt',
99+
size: 'small'
100+
});
101+
```
76102

103+
Because record.size is used to return the records count (similar to array.length), the above definition would throw an error.

0 commit comments

Comments
 (0)