https://github.com/iroy2000/immutablejs-for-beginners
This documentation is trying to help people who starts using FB immutable.js but at the same time feeling confused by the original documentation
https://github.com/iroy2000/immutablejs-for-beginners
documentation immutablejs
Last synced: 3 months ago
JSON representation
This documentation is trying to help people who starts using FB immutable.js but at the same time feeling confused by the original documentation
- Host: GitHub
- URL: https://github.com/iroy2000/immutablejs-for-beginners
- Owner: iroy2000
- Created: 2016-09-25T20:08:24.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2018-03-15T20:45:11.000Z (almost 8 years ago)
- Last Synced: 2024-12-28T06:25:23.733Z (about 1 year ago)
- Topics: documentation, immutablejs
- Size: 10.7 KB
- Stars: 24
- Watchers: 3
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Immutable.js for beginners
This documentation is trying to help people who start using [immutable.js](https://facebook.github.io/immutable-js/) but at the same time feeling confused by the original overwhelming documentation.
**Worth Mentioning:** The documentation syntax of [immutable.js](https://facebook.github.io/immutable-js/) is written with [Typescript](http://www.typescriptlang.org/docs/handbook/basic-types.html), so if you are confused, it is not your fault :)
**If you are looking for basic concepts**, please look at the last section `Resources`, I put up a few links to hook you up with some important concepts in Immutable / Immutablejs.
## Join our conversation for Immutable.js for beginners on [Slack](https://immutablejs4beginners.slack.com/)
## Table of Contents
* [Map](#map)
* [List](#list)
* [Other Data Structure](#other-data-structure) (Set, Record, Seq)
* [Resources](#resources)
* [Contributions](#contributions)
## Map
Assume:
* you have imported your immutablejs somewhere
* and, you have the following data structure
```javascript
import { Map } from 'immutable'
let me = Map({
name: 'roy',
hobby: 'reading'
})
```
The following will showcase basic operations for map
```javascript
me.name // undefined, you can't reference the properties directly
me.get('name') // roy
me.set('name', 'iroy2000') // setting values
me.get('name') // roy ( what ??? )
// !!! Remember in immutable.js when you "mutate" the data,
// it does not modify the original value, but it will return a new one
// -----------------------------------------------------------------------
me = me.set('name', 'iroy2000') // setting values
me.get('name') // iroy2000 ( ah !!! )
me = me.update('name', item => item.toUppercase)
me.get('name') // IROY2000
```
The following to show case you can merge with a plain object
```javascript
let map2 = Map({
age: '> 20'
})
let mapPlainObject = {
gender: 'male'
}
// ImmutableJS treat JavaScript Array or Object as an Iterable
// ----------------------------------------------------------------
me.merge(map2, mapPlainObject) // now the map includes age and gender: { "name": "IROY2000", "hobby": "reading", "age": "> 20", "gender": "male" }
```
**Equality Checking**
Note that the equality checking is applied to not just Map only but to others as well.
Assume that you have the following data structure
```javascript
import { Map } from 'immutable'
let config = {
name: 'roy',
hobby: 'reading'
}
let me1 = Map(config)
let me2 = Map(config)
me1 == me2 // false
me1.equals(me2) // true
// If you just want to compare if they have same keys
// ----------------------------------------------------------------
map2.keySeq().equals(me.keySeq())
```
**Note:** If you don't understand what is Iterable, it is a collection of objects that allow you to iterate through ( or loop through ) with functions like `map()`, `filter()` or native js `for ... in`. Here is the official documentation in immutablejs on [Iterable](https://facebook.github.io/immutable-js/docs/#/Iterable), and here is a [StackOverflow](http://stackoverflow.com/questions/18884249/checking-whether-something-is-iterable) link if you need more insight.
The following showcase some common cases for a map
```javascript
map1.has(['name']) // true
map1.map((value, key) => `$value is cool`)
```
**Dealing with Nested structure**
Assume you have the following structure for your map
```javascript
// The following show case you can create immutable data struture
// directly from plain js object using fromJS helper function
// Just remember "array" -> "List" while "object" --> "Map"
// ----------------------------------------------------------------
import { fromJS } from 'immutable'
let me = fromJS({
name: 'roy',
profile: {
gender: 'male',
language:'javascript'
}
})
```
The following will explain how to performing deep values getting / setting
```javascript
me = me.setIn(['profile', 'language'], 'awesome javascript')
// The following two "gets" are the same
// ------------------------------------------
me.get('profile').get('language') // awesome javascript
me.getIn(['profile', 'language']) // awesome javascript
me = me.mergeDeep({
profile : {
hobby: 'reading'
}
})
me.getIn(['profile', 'hobby']) // reading
me = me.updateIn(['profile', 'hobby'], item => .toUpperCase())
me.getIn(['profile', 'hobby']) // READING
// The following will grab the profile data
// and delete the key = "hobby" entry in it
// -------------------------------------------
me.updateIn(['profile'], profile => profile.delete('hobby'))
```
**Note** `fromJS` is a convenience function that convert nested Objects and Arrays into immutable `Map` and `List` automatically. So if you are using `fromJS`, **do not** apply or mix `Map` or `List` as you could introduce unintentional bugs.
## List
#### Assume you have the following data structure
In immutable.js, most of the data structure shares a lot of the same functionalities, because they are inheriting from the same data structure - [Iterable](https://facebook.github.io/immutable-js/docs/#/Iterable)
It supports javascript array-like operations, for example, `pop`, `push`, `concat`, `shift` ...
```javascript
import { List } from 'immutable'
let items = List([1,2,3,4])
items = items.push(5) // 1,2,3,4,5
items = items.pop() // 1,2,3,4
items = items.concat(5, 6) // 1,2,3,4,5,6
items = items.shift() // 2,3,4,5,6
```
```javascript
import { fromJS } from 'immutable'
// Remember "array" -> "List" while "object" --> "Map"
// ------------------------------------------------------
let me = fromJS({
name: 'roy',
friends: [
{
name: 'captain america',
properties: {
equipment: 'shield'
}
},
{
name: 'iron man',
properties: {
equipment: 'armor'
}
},
{
name: 'thor',
properties: {
equipment: 'hammer'
}
}
]
})
```
```javascript
me.get('friends').get(0).get('name') // captain america
me.getIn(['friends', 0, 'name']) // captain america
me.get('friends').get(0).get('properties').get('equipment') // shield
me.getIn(['friends', 0, 'properties', 'equipment']) // shield
me = me.setIn(['friends', 0, 'properties', 'equipment'], 'glove');
let hulk = {
name: 'hulk',
properties: {
equipment: 'body'
}
}
// now you have new friends
me = me.update('friends', friends => friends.push(hulk))
let friendYouWantToKnowTheIndex = me.get('friends').findIndex(friend => {
return friend.get('name') === 'captain america'
})
me = me.setIn(['friends', friendYouWantToKnowTheIndex, 'equipment'], 'shield')
// How about shuffling all your friends ?
// A better version would be a custom comparator
// -----------------------------------------------
list = me.update('friends',
friends => friends.sortBy(() => Math.random())
)
```
The following show case some common use case for a List
```javascript
let heroSalaryList = Immutable.List([
{name: 'Thor', salary: 1000},
{name: 'Iron Man', salary: 500},
{name: 'Hawkeye', salary: 300}
])
// Iterate through the list and reduce the list to a value
// For example, add all salaries of heroes
// ( and divide by number of heroes )
// ----------------------------------------------------------
let averageSalary = heroSalaryList.reduce((total, hero) => {
return total + hero.salary
}, 0) / heroSalaryList.count()
averageSalary == 600 // true
// fitler the list whose salary cannot be divided by 500
// ----------------------------------------------------------
let filteredHeroSalaryList = heroSalaryList.filter(
hero => hero.salary % 500 > 1
)
filteredHeroSalaryList.count() // only 1 left
filteredHeroSalaryList.get(0).get('name') // Hawkeye
```
## Other Data Structure
#### Set
An array ( or iterable type ) of unique elements and it will remove any duplicates.
```javascript
import { Set } from 'immutable'
let set1 = Set([1,1,2,2,3,3])
set1.count() // 3
set1.toArray() // 1,2,3
// You can perform subtract, intersect and union on a set.
// But if your set is objects, in order to do that safely,
// you will have to create variables before creating the set.
const set2 = Set(['hello', 'world', 'what', 'up']);
set2.subtract['hello'] // it will remove the value from the set
// consider the following case, which the set contains objects
const greet1 = { 'hello': 'world' };
const greet2 = { 'what': 'up' };
const greetSet = Set([greet1, greet2]);
greetSet.subtract([{'hello': 'world'}]); // !!! It won't work !!!
greetSet.subtract([greet1]); // It will work
```
#### Record
Record let you create a javascript class that comes with default values.
```javascript
import { Record } from 'immutable'
let Villian = Record({
skill: 'do very bad thing'
})
let joker = new Villian({
skill: 'playing poker'
})
joker.toJSON() // { skill: 'playing poker' }
// It will fall back to default value
// if you remove it
// -----------------------------------------------
joker = joker.remove('skill')
joker.toJSON() // { skill: 'do very bad thing' }
// Values provided to the constructor not found
// in the Record type will be ignored.
// -----------------------------------------------
let batwoman = new Villian({
hairstyle: 'cool'
})
batwoman.toJSON() // { skill: 'do very bad thing' }
```
#### Seq ( Lazy Operation )
Lazy operation means that the chain methods ( operations ) are not executed until it is requested. And it will stop the execution when the returned items fulfill the request.
```javascript
import { Seq } from 'immutable'
// Note: The order of the items are important
// ------------------------------------------------------------------
var femaleHero = Seq.of(
{name:'thor', gender: 'male'},
{name:'hulk', gender: 'male'},
{name:'black widow', gender: 'female'}
)
.filter(hero => hero.gender == 'female')
.map(hero => `${hero.name} is a ${hero.gender}`)
// Only performs as much work as necessary to get the result
// ------------------------------------------------------------------
femaleHero // Nothing will be called
// This will iterate all three items until the
// first "true" return. All three hero are iterated
// util we found one "female hero" to return.
// ------------------------------------------------------------------
femaleHero.get(0) // return 'black widow is a female'
// If we change the order of the Seq, the first "true" will
// return and the rest of the operations will not even get called.
//
// For example:
// The request of getting first "female hero" is fulfilled,
// the progrm terminates, which means the next operation of
// `filter()` and `map()` will not even get called.
// ------------------------------------------------------------------
{name:'black widow', gender: 'female'},
{name:'thor', gender: 'male'},
{name:'hulk', gender: 'male'}
```
## Resources
#### Readings
* [Introduction to Immutablejs](https://auth0.com/blog/intro-to-immutable-js/)
* [Immutablejs overview](http://www.darul.io/post/2015-07-06_immutablejs-overview)
#### Toolings
* [Immutable live tutorial](http://blog.klipse.tech/javascript/2016/03/30/immutable.html)
* [immutable-docs](http://brentburg.github.io/immutable-docs/api)
## Contributions
**Pull Request are welcomed !!!** Hopefully it will be a **community driven** effort to make other developers' life easier when learning immutable.js
***PR*** could include more examples, better introduction, presentations, resources ... etc.