Immer JS - Technological watch
Problematic
In JavaScript, when we use arrays, we can be confronted with this problem:
const items = [1, 8, 5, 3];const sorted = items.sort();
if (items === sorted) { // this condition is true ! // But why ?}
Here, the sort()
method change the items
variable instead of creating a new array.
We say that sort()
makes a mutation.
To avoid this, we have to create a copy of the items
array:
Here is an example:
const items = [1, 3, 5, 8];
const newItems = [...items]; // Create a copy before sortingnewItems.sort();
// Here, items !== newItems
But in some cases, using immutable data in JavaScript can be hard. Let’s pick an easy example:
const todos = [ { title: "Do technological watch", completed: true }, { title: "Clean my room", completed: false }, { title: "Prepare a gift for my friends", completed: false },];
Imagine you have a to-do list, and you want to create a function which toggles one to-do (without changing or mutating).
You have to do something like this:
const toggleTodo = (todos, index) => { return todos.map((todo, i) => i === index ? { ...todo, completed: !todo.completed, } : todo );};
// -----
toggleTodo(todos, 1);
// returns:[ { title: "Do technological watch", completed: true }, { title: "Clean my room", completed: true }, { title: "Prepare a gift for my friends", completed: false },];
// And "todos" isn't modified !
Look at the syntax. It isn’t natural, right ? And here, we have a simple case (we only want to toggle one to-do !).
Now imagine we have a more complex case ! 😱
A solution: ImmerJS
ImmerJS is a JavaScript library used to simplify the handling of immutable data structures.
You can find more information by following this link: https://immerjs.github.io/immer/. To import it in your projects, you can do:
npm install immer# 3KB gzipped
To play with a state, you just have to use a produce
function which receive the state
, and a draft
in parameter.
The draft is the new version of the state. You can do any modifications you want as imperative code.
Here’s an example:
import produce from "immer";
const baseState = [ { title: "Learn TypeScript", completed: true, }, { title: "Try Immer", completed: false, },];
const nextState = produce(baseState, (draftState) => { draftState.push({ title: "Tweet about it" }); draftState[1].done = true;});
// Here, baseState !== nextState
Immer returns the new immutable state. The big advantage is that the library offers a simple and readable way to make complex tasks.
Work with React JS
Immer works great with ReactJS.
Immer provided some hooks.
Let’s take a look with the useImmer
hook:
import React, { useCallback } from "react";import { useImmer } from "use-immer";
const TodoList = () => { const [todos, setTodos] = useImmer([ { id: "React", title: "Learn React", done: true }, { id: "Immer", title: "Try Immer", done: false } ]);
const handleToggle = useCallback((id) => { setTodos((draft) => { const todo = draft.find((todo) => todo.id === id); todo.done = !todo.done; }); }, []);
const handleAdd = useCallback(() => { setTodos((draft) => { draft.push({ id: "todo_" + Math.random(), title: "A new todo", done: false }); }); }, []);
// etc
Easier right ?
Other supports
-
ImmerJS supports more complex data structures like
Map
/Set
orClasses
. -
It offers other easy APIs and even a patch system !
-
Finally, it fully supports Typescript, so no any types problems anymore !
My opinion
ImmerJS is a great small library to avoid the mutable state problem.
The final code is cleaner, and no needs to think about hacks.
With ImmerJS, it is easier to solve some ReactJS / functional cases.
Atomic design - Technological watch
Learn what is the atomic design in less than 5 minutes !
Redis - Technological watch
Learn what is Redis in less than 5 minutes !
Svelte - Technological watch
Learn what is Svelte in less than 5 minutes !
OpenAPI / Swagger - Technological watch
Learn what is OpenAPI / Swagger in less than 5 minutes !
RabbitMQ - Technological watch
Learn what is RabbitMQ in less than 5 minutes !
Falco - Technological watch
Learn how to protect your Kubernetes cluster in less than 5 minutes !
Atomic distribution - Fedora Silverblue - Technological watch
Learn what is an Atomic distribution in less than 5 minutes !
PicoCSS - Technological watch
Learn what is PicoCSS in less than 5 minutes !