Immutable JavaScript Data Structures with Immer

Brought by: egghead.io

Overview

Using immutable data structures provides many benefits, including making your code easier to reason about and less prone to bugs.
However, since JavaScript doesn't include support for immutable data structures out of the box, you need to use a third party library. But which one to choose?
In this self-paced workshop, Immer's creator Michel Westrate will guide you through the creation of a multi-user Gift Tracking app.
You'll learn the basics of using Immer to handle immutable state updates, then go further into change distribution and implementing an undo/redo.
After this workshop, you'll be ready to leverage immutable data structures in your own applications!

Syllabus

  • Introduction to the in-depth Immer course
  • Capture Application Logic in Pure Functions to Create Immutable State
  • Simplify Deep State Updates using Immer produce
  • Render Immutable Data using React
  • Profile React Rendering and Optimize with memo to Leverage Structural Sharing
  • Simplify Immer Producer Functions using Currying
  • Produces Immutable Data and Avoid Unnecessary Creation of New Data Trees with Immer
  • Immutable Update State inside React components with useImmer
  • Return Completely New State from an Immer Producer
  • Avoid Accidental Returns of New State by using the void Keyword
  • Write Asynchronous Producers in Immer and Why You Shouldn’t
  • Type Immutable Immer Data with TypeScript
  • Update Immutable State with React useReducer through Immer
  • Capture Patches to Distribute Changes in App State with Immer produceWithPatches
  • Create a Simple WebSocket Server to Distribute Patches from Immer
  • Apply Patches using Immer applyPatches to Synchronize State across Clients
  • Create Stable Patches in Immer by updating with Id instead of Indices
  • Compress the Immer Patch History by Replaying Patches on a setInterval
  • Use Immer inversePatches to Build Undo Functionality
  • Use Immer Patches to Build Redo Functionality

Taught by

Michel Weststrate

Immutable JavaScript Data Structures with Immer
Go to course

Immutable JavaScript Data Structures with Immer

Brought by: egghead.io

  • egghead.io
  • Free
  • English
  • Certificate Not Available
  • Available at any time
  • All
  • N/A
8.1.2PHP Version922msRequest Duration2MBMemory UsageGET en/courses/{slug}Route
    • Booting (595ms)
    • Application (324ms)
    • 1 x Booting (64.53%)
      595.02ms
      1 x Application (35.17%)
      324.33ms
      14 templates were rendered
      • public.courses.show (resources/views/public/courses/show.blade.php)3bladefile
        Params
        0
        course
        1
        links
        2
        config
      • public.courses.partials.breadcrumbs (resources/views/public/courses/partials/breadcrumbs.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.courses.partials.heading (resources/views/public/courses/partials/heading.blade.php)7bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
        6
        classes
      • public.courses.partials.details (resources/views/public/courses/partials/details.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.courses.partials.breadcrumbs (resources/views/public/courses/partials/breadcrumbs.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.courses.partials.heading (resources/views/public/courses/partials/heading.blade.php)7bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
        6
        classes
      • public.layouts.main (resources/views/public/layouts/main.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.layouts.partials.meta (resources/views/public/layouts/partials/meta.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.layouts.partials.navbar (resources/views/public/layouts/partials/navbar.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.auth.profile.partials.links (resources/views/public/auth/profile/partials/links.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      • public.auth.profile.partials.link (resources/views/public/auth/profile/partials/link.blade.php)8bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
        6
        route
        7
        title
      • public.auth.profile.partials.link (resources/views/public/auth/profile/partials/link.blade.php)8bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
        6
        route
        7
        title
      • public.auth.profile.partials.link (resources/views/public/auth/profile/partials/link.blade.php)8bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
        6
        route
        7
        title
      • public.layouts.partials.flash-session (resources/views/public/layouts/partials/flash-session.blade.php)6bladefile
        Params
        0
        __env
        1
        app
        2
        errors
        3
        course
        4
        links
        5
        config
      uri
      GET en/courses/{slug}
      middleware
      web, localize:en
      controller
      App\Http\Controllers\CourseController@show
      as
      en.courses.show
      namespace
      prefix
      /en
      where
      file
      app/Http/Controllers/CourseController.php:17-35
      6 statements were executed11.81ms
      • select * from `courses` where `slug_en` = 'immutable-javascript-data-structures-with-immer' limit 1
        10.34ms/app/Http/Controllers/CourseController.php:20corspedia
        Metadata
        Bindings
        • 0. immutable-javascript-data-structures-with-immer
        Backtrace
        • 17. /app/Http/Controllers/CourseController.php:20
        • 18. /vendor/laravel/framework/src/Illuminate/Routing/Controller.php:54
        • 19. /vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:43
        • 20. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:260
        • 21. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:205
      • update `courses` set `visitors` = `visitors` + 1, `courses`.`updated_at` = '2025-06-28 18:28:53' where `id` = 1728
        550μs/app/Http/Controllers/CourseController.php:21corspedia
        Metadata
        Bindings
        • 0. 2025-06-28 18:28:53
        • 1. 1728
        Backtrace
        • 17. /app/Http/Controllers/CourseController.php:21
        • 18. /vendor/laravel/framework/src/Illuminate/Routing/Controller.php:54
        • 19. /vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:43
        • 20. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:260
        • 21. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:205
      • select `id`, `name_en`, `name_ar`, `topic_id`, `slug_en`, `slug_ar` from `subjects` where `subjects`.`id` in (6)
        240μs/app/Http/Controllers/CourseController.php:23corspedia
        Metadata
        Backtrace
        • 20. /app/Http/Controllers/CourseController.php:23
        • 21. /vendor/laravel/framework/src/Illuminate/Routing/Controller.php:54
        • 22. /vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:43
        • 23. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:260
        • 24. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:205
      • select `id`, `name_en`, `name_ar`, `slug_en`, `slug_ar` from `topics` where `topics`.`id` in (1)
        200μs/app/Http/Controllers/CourseController.php:23corspedia
        Metadata
        Backtrace
        • 25. /app/Http/Controllers/CourseController.php:23
        • 26. /vendor/laravel/framework/src/Illuminate/Routing/Controller.php:54
        • 27. /vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:43
        • 28. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:260
        • 29. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:205
      • select * from `providers` where `providers`.`id` in (29) and `providers`.`deleted_at` is null
        220μs/app/Http/Controllers/CourseController.php:23corspedia
        Metadata
        Backtrace
        • 20. /app/Http/Controllers/CourseController.php:23
        • 21. /vendor/laravel/framework/src/Illuminate/Routing/Controller.php:54
        • 22. /vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:43
        • 23. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:260
        • 24. /vendor/laravel/framework/src/Illuminate/Routing/Route.php:205
      • select * from `html_files` where `html_files`.`id` = 1719 limit 1
        260μs/app/Models/Course.php:84corspedia
        Metadata
        Bindings
        • 0. 1719
        Backtrace
        • 21. /app/Models/Course.php:84
        • 28. view::public.courses.show:29
        • 30. /vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php:125
        • 31. /vendor/laravel/framework/src/Illuminate/View/Engines/PhpEngine.php:58
        • 32. /vendor/laravel/framework/src/Illuminate/View/Engines/CompilerEngine.php:72
      App\Models\HtmlFile
      1
      App\Models\Provider
      1
      App\Models\Topic
      1
      App\Models\Subject
      1
      App\Models\Course
      1
        _token
        V5P8mKxKvyvKhbE5434h56TLJZ6zs5151chIJh4Q
        locale
        en
        _previous
        array:1 [ "url" => "https://www.corspedia.com/en/courses/immutable-javascript-data-structures-with...
        _flash
        array:2 [ "old" => [] "new" => [] ]
        PHPDEBUGBAR_STACK_DATA
        []
        path_info
        /en/courses/immutable-javascript-data-structures-with-immer
        status_code
        200
        
        status_text
        OK
        format
        html
        content_type
        text/html; charset=UTF-8
        request_query
        []
        
        request_request
        []
        
        request_headers
        0 of 0
        array:24 [ "cf-ipcountry" => array:1 [ 0 => "US" ] "cf-connecting-ip" => array:1 [ 0 => "216.73.216.68" ] "cdn-loop" => array:1 [ 0 => "cloudflare; loops=1" ] "x-forwarded-proto" => array:1 [ 0 => "https" ] "x-forwarded-for" => array:1 [ 0 => "216.73.216.68" ] "sec-fetch-site" => array:1 [ 0 => "none" ] "accept" => array:1 [ 0 => "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" ] "user-agent" => array:1 [ 0 => "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)" ] "upgrade-insecure-requests" => array:1 [ 0 => "1" ] "sec-ch-ua-platform" => array:1 [ 0 => ""Windows"" ] "sec-ch-ua-mobile" => array:1 [ 0 => "?0" ] "sec-ch-ua" => array:1 [ 0 => ""Chromium";v="130", "HeadlessChrome";v="130", "Not?A_Brand";v="99"" ] "cache-control" => array:1 [ 0 => "no-cache" ] "pragma" => array:1 [ 0 => "no-cache" ] "sec-fetch-dest" => array:1 [ 0 => "document" ] "cf-ray" => array:1 [ 0 => "956f3f145c14024e-ORD" ] "accept-encoding" => array:1 [ 0 => "gzip, br" ] "priority" => array:1 [ 0 => "u=0, i" ] "sec-fetch-user" => array:1 [ 0 => "?1" ] "sec-fetch-mode" => array:1 [ 0 => "navigate" ] "cf-visitor" => array:1 [ 0 => "{"scheme":"https"}" ] "host" => array:1 [ 0 => "www.corspedia.com" ] "content-length" => array:1 [ 0 => "" ] "content-type" => array:1 [ 0 => "" ] ]
        request_server
        0 of 0
        array:50 [ "USER" => "www-data" "HOME" => "/var/www" "HTTP_CF_IPCOUNTRY" => "US" "HTTP_CF_CONNECTING_IP" => "216.73.216.68" "HTTP_CDN_LOOP" => "cloudflare; loops=1" "HTTP_X_FORWARDED_PROTO" => "https" "HTTP_X_FORWARDED_FOR" => "216.73.216.68" "HTTP_SEC_FETCH_SITE" => "none" "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" "HTTP_USER_AGENT" => "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)" "HTTP_UPGRADE_INSECURE_REQUESTS" => "1" "HTTP_SEC_CH_UA_PLATFORM" => ""Windows"" "HTTP_SEC_CH_UA_MOBILE" => "?0" "HTTP_SEC_CH_UA" => ""Chromium";v="130", "HeadlessChrome";v="130", "Not?A_Brand";v="99"" "HTTP_CACHE_CONTROL" => "no-cache" "HTTP_PRAGMA" => "no-cache" "HTTP_SEC_FETCH_DEST" => "document" "HTTP_CF_RAY" => "956f3f145c14024e-ORD" "HTTP_ACCEPT_ENCODING" => "gzip, br" "HTTP_PRIORITY" => "u=0, i" "HTTP_SEC_FETCH_USER" => "?1" "HTTP_SEC_FETCH_MODE" => "navigate" "HTTP_CF_VISITOR" => "{"scheme":"https"}" "HTTP_HOST" => "www.corspedia.com" "REDIRECT_STATUS" => "200" "SERVER_NAME" => "corspedia.com" "SERVER_PORT" => "443" "SERVER_ADDR" => "141.95.147.152" "REMOTE_USER" => "" "REMOTE_PORT" => "49308" "REMOTE_ADDR" => "172.70.178.24" "SERVER_SOFTWARE" => "nginx/1.18.0" "GATEWAY_INTERFACE" => "CGI/1.1" "HTTPS" => "on" "REQUEST_SCHEME" => "https" "SERVER_PROTOCOL" => "HTTP/2.0" "DOCUMENT_ROOT" => "/var/www/corspedia/public" "DOCUMENT_URI" => "/index.php" "REQUEST_URI" => "/en/courses/immutable-javascript-data-structures-with-immer" "SCRIPT_NAME" => "/index.php" "CONTENT_LENGTH" => "" "CONTENT_TYPE" => "" "REQUEST_METHOD" => "GET" "QUERY_STRING" => "" "SCRIPT_FILENAME" => "/var/www/corspedia/public/index.php" "PATH_INFO" => "" "FCGI_ROLE" => "RESPONDER" "PHP_SELF" => "/index.php" "REQUEST_TIME_FLOAT" => 1751135332.7934 "REQUEST_TIME" => 1751135332 ]
        request_cookies
        []
        
        response_headers
        0 of 0
        array:5 [ "content-type" => array:1 [ 0 => "text/html; charset=UTF-8" ] "cache-control" => array:1 [ 0 => "no-cache, private" ] "date" => array:1 [ 0 => "Sat, 28 Jun 2025 18:28:53 GMT" ] "set-cookie" => array:2 [ 0 => "XSRF-TOKEN=eyJpdiI6IjZGYnloVXZFMzE3NVlSTVJMTll4QUE9PSIsInZhbHVlIjoicEV5MnJGTkJvaUFyVm9oVjhML0NDZ3JJYnpwc3JZdVluWXV6VXhVUERtQ3BQakluWTU3SGlNbTVpUHVlQ2ZsOVRjWlg0YXpJNG5pSGJzWDU4OFNjN21xV0FVcFNwSldJUUhGQmFqaThqcXp3ckZpNlFDN0c0UStSNXQ3aTVSQUciLCJtYWMiOiJiZTdkNzRjOTVmY2UyMThmZGNhZWMzNjc3YjYxMWU0Y2RiMWVlZjllNjJkNWY5NjFkNmQwY2ViNGM4MWVmZmZlIiwidGFnIjoiIn0%3D; expires=Sat, 28 Jun 2025 20:28:53 GMT; Max-Age=7200; path=/; samesite=laxXSRF-TOKEN=eyJpdiI6IjZGYnloVXZFMzE3NVlSTVJMTll4QUE9PSIsInZhbHVlIjoicEV5MnJGTkJvaUFyVm9oVjhML0NDZ3JJYnpwc3JZdVluWXV6VXhVUERtQ3BQakluWTU3SGlNbTVpUHVlQ2ZsOVRjWlg0Y" 1 => "laravel_session=eyJpdiI6IkdVdUVWT2JGakY0ZjI1OFJ2ajlkZ1E9PSIsInZhbHVlIjoiNFN3SmhLbjc0YXVXd3pORTViWFNpbXhNK2lOZ2pzWVdWbDUzYnN6aVU1WGlLYVZoZ3J1RmM4M3lmcFhEUmptVXFoYjFiUnoxT1c2UWVKZHVjUkNMRHM4eUJGU05SdVB4QlRiM1NZZFJNTnRpUlZtSkJ2TkNjZjZUeStzZ0R5UGMiLCJtYWMiOiI3NzJmMDA5MGY5MzcxNzA2ZmMxMjVjOWYzZmZkZDAxMTJhNDZlMzU3NzMyOGU1OTBiODVmMTU0MTRjMWE0ZTZjIiwidGFnIjoiIn0%3D; expires=Sat, 28 Jun 2025 20:28:53 GMT; Max-Age=7200; path=/; httponly; samesite=laxlaravel_session=eyJpdiI6IkdVdUVWT2JGakY0ZjI1OFJ2ajlkZ1E9PSIsInZhbHVlIjoiNFN3SmhLbjc0YXVXd3pORTViWFNpbXhNK2lOZ2pzWVdWbDUzYnN6aVU1WGlLYVZoZ3J1RmM4M3lmcFhEUmptVXFo" ] "Set-Cookie" => array:2 [ 0 => "XSRF-TOKEN=eyJpdiI6IjZGYnloVXZFMzE3NVlSTVJMTll4QUE9PSIsInZhbHVlIjoicEV5MnJGTkJvaUFyVm9oVjhML0NDZ3JJYnpwc3JZdVluWXV6VXhVUERtQ3BQakluWTU3SGlNbTVpUHVlQ2ZsOVRjWlg0YXpJNG5pSGJzWDU4OFNjN21xV0FVcFNwSldJUUhGQmFqaThqcXp3ckZpNlFDN0c0UStSNXQ3aTVSQUciLCJtYWMiOiJiZTdkNzRjOTVmY2UyMThmZGNhZWMzNjc3YjYxMWU0Y2RiMWVlZjllNjJkNWY5NjFkNmQwY2ViNGM4MWVmZmZlIiwidGFnIjoiIn0%3D; expires=Sat, 28-Jun-2025 20:28:53 GMT; path=/XSRF-TOKEN=eyJpdiI6IjZGYnloVXZFMzE3NVlSTVJMTll4QUE9PSIsInZhbHVlIjoicEV5MnJGTkJvaUFyVm9oVjhML0NDZ3JJYnpwc3JZdVluWXV6VXhVUERtQ3BQakluWTU3SGlNbTVpUHVlQ2ZsOVRjWlg0Y" 1 => "laravel_session=eyJpdiI6IkdVdUVWT2JGakY0ZjI1OFJ2ajlkZ1E9PSIsInZhbHVlIjoiNFN3SmhLbjc0YXVXd3pORTViWFNpbXhNK2lOZ2pzWVdWbDUzYnN6aVU1WGlLYVZoZ3J1RmM4M3lmcFhEUmptVXFoYjFiUnoxT1c2UWVKZHVjUkNMRHM4eUJGU05SdVB4QlRiM1NZZFJNTnRpUlZtSkJ2TkNjZjZUeStzZ0R5UGMiLCJtYWMiOiI3NzJmMDA5MGY5MzcxNzA2ZmMxMjVjOWYzZmZkZDAxMTJhNDZlMzU3NzMyOGU1OTBiODVmMTU0MTRjMWE0ZTZjIiwidGFnIjoiIn0%3D; expires=Sat, 28-Jun-2025 20:28:53 GMT; path=/; httponlylaravel_session=eyJpdiI6IkdVdUVWT2JGakY0ZjI1OFJ2ajlkZ1E9PSIsInZhbHVlIjoiNFN3SmhLbjc0YXVXd3pORTViWFNpbXhNK2lOZ2pzWVdWbDUzYnN6aVU1WGlLYVZoZ3J1RmM4M3lmcFhEUmptVXFo" ] ]
        session_attributes
        0 of 0
        array:5 [ "_token" => "V5P8mKxKvyvKhbE5434h56TLJZ6zs5151chIJh4Q" "locale" => "en" "_previous" => array:1 [ "url" => "https://www.corspedia.com/en/courses/immutable-javascript-data-structures-with-immer" ] "_flash" => array:2 [ "old" => [] "new" => [] ] "PHPDEBUGBAR_STACK_DATA" => [] ]