All Projects → iroy2000 → Immutablejs For Beginners

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

Projects that are alternatives of or similar to Immutablejs For Beginners

Lemonade Stand
A handy guide to financial support for open source
Stars: ✭ 6,513 (+25952%)
Mutual labels:  documentation
Everything Curl
The book documenting the curl project, the curl tool, libcurl and everything related to this.
Stars: ✭ 885 (+3440%)
Mutual labels:  documentation
Aruba
Test command-line applications with Cucumber-Ruby, RSpec or Minitest. The most up to date documentation can be found on Cucumber.Pro (https://app.cucumber.pro/projects/aruba)
Stars: ✭ 900 (+3500%)
Mutual labels:  documentation
Nginx Docs
Nginx 中文文档. Chinese translation of Nginx documentation.
Stars: ✭ 809 (+3136%)
Mutual labels:  documentation
Apispec
A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification)..
Stars: ✭ 831 (+3224%)
Mutual labels:  documentation
Fed.ialis.me
a guide to the fediverse -- WIP
Stars: ✭ 17 (-32%)
Mutual labels:  documentation
Tech Radar
Visualizing our technology choices
Stars: ✭ 787 (+3048%)
Mutual labels:  documentation
Wsl Programs
A community powered list of programs that work (and those that don't) on the Windows subsystem for Linux
Stars: ✭ 931 (+3624%)
Mutual labels:  documentation
Entityframework.docs
Documentation for Entity Framework Core and Entity Framework 6
Stars: ✭ 888 (+3452%)
Mutual labels:  documentation
Documentation
Documentation for the STUPS ecosystem
Stars: ✭ 18 (-28%)
Mutual labels:  documentation
Docpress
Documentation website generator
Stars: ✭ 815 (+3160%)
Mutual labels:  documentation
Devtools
The Hoa\Devtools library.
Stars: ✭ 5 (-80%)
Mutual labels:  documentation
Api schema
DSL for describing APIs and generate swagger json
Stars: ✭ 18 (-28%)
Mutual labels:  documentation
Couscous
Couscous is good.
Stars: ✭ 807 (+3128%)
Mutual labels:  documentation
Wiki
Official repository for OCS Inventory documentaiton
Stars: ✭ 23 (-8%)
Mutual labels:  documentation
Site
🎓 Rust Programming Language Tutorials for Everyone!
Stars: ✭ 786 (+3044%)
Mutual labels:  documentation
Knowledgebase
Knowledge is Power
Stars: ✭ 17 (-32%)
Mutual labels:  documentation
Platform Documentation
Core Platform API Documentation & Tutorials
Stars: ✭ 25 (+0%)
Mutual labels:  documentation
Doc Hunt
Keep your documentation up to date by tracking changes in your source code
Stars: ✭ 24 (-4%)
Mutual labels:  documentation
Docker Cheat Sheet
A collection of recipes for docker.
Stars: ✭ 18 (-28%)
Mutual labels:  documentation

Immutable.js for beginners

This documentation is trying to help people who start using immutable.js but at the same time feeling confused by the original overwhelming documentation.

Worth Mentioning: The documentation syntax of immutable.js is written with Typescript, 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

Table of Contents

Map

Assume:

  • you have imported your immutablejs somewhere
  • and, you have the following data structure
import { Map } from 'immutable'

let me = Map({
  name: 'roy',
  hobby: 'reading'
})

The following will showcase basic operations for map

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

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

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, and here is a StackOverflow link if you need more insight.

The following showcase some common cases for a map

map1.has(['name'])  // true

map1.map((value, key) => `$value is cool`)

Dealing with Nested structure

Assume you have the following structure for your map

// 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

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

It supports javascript array-like operations, for example, pop, push, concat, shift ...

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

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'
      }
    }
  ]
})

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

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.

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.

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.

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

Toolings

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.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].