use-immer-reactn

React hook and helper function for using Immer with ReactN

Usage no npm install needed!

<script type="module">
  import useImmerReactn from 'https://cdn.skypack.dev/use-immer-reactn';
</script>

README

Use Immer ReactN

version downloads

React hook and helper function for using Immer with ReactN.

Install

  • npm install use-immer-reactn or
  • yarn add use-immer-reactn

Usage

Assuming your global state set in ReactN looks like this:

{
    title: {
        en: 'Hello World'
    }
}

useGlobalImmer

Works very similar to useGlobal in ReactN with the one different being you pass a function (producer) to the "setValue" call instead of a new value.

The passed function works exactly the same as a "producer" in Immer. Receiving the original value as it's only parameter which may be mutated at will.

import {useGlobalImmer} from 'use-immer-reactn';

const TestComponent = () => {
    const [ title, setTitle ] = useGlobalImmer( 'title' );

    const changeTitleProducer = ( originalTitle ) => {
        originalTitle.en += ' Changed';
    };

    return (
        <>
            <h1>{title.en}</h1>
            <button onClick={() => setTitle( changeTitleProducer )}/>
        </>
    );
};
export default TestComponent;

Simplified

export default () => {
    const [ title, setTitle ] = useGlobalImmer( 'title' );
    return (
        <>
            <h1>{title.en}</h1>
            <button onClick={() => setTitle( draft => {
                draft.en += ' Changed';
            } )}/>
        </>
    );
};

You may omit the property when calling useGlobalImmer to work with the entire state object.

export default () => {
    const [ state, setState] = useGlobalImmer();
    return (
        <>
            <h1>{state.title.en}</h1>
            <button onClick={() => setTitle( draft => {
                draft.title.en += ' Changed';
            } )}/>
        </>
    );
};

You may also pass a finished object instead of a callback to the updater function. This allows to externally finish an object and or mutate a draft from the same useGlobalImmer updater interchangeably.

export default () => {
    const [ title, setTitle ] = useGlobalImmer( 'title' );
    return (
        <>
            <h1>{title.en}</h1>
        {/** Using a finished object **/}
            <button
                onClick={() => setTitle( {
                    en : 'changed'
                })} />
        {/** Using a draft mutator callback **/}
            <button
                onClick={() => setTitle( draft => {
                    draft.en += ' Changed';
                } )} />
        </>
    );
};

setGlobalImmer

Works very similar to setGlobal in ReactN with two differences:

  1. An (optional) property may be specified to work with just that key instead of the entire global state.
  2. A function (producer) is passed instead of the new value.

Passing a property

The passed function works exactly the same as a "producer" in Immer. Receiving the original value of the specified key as it's only parameter which may be mutated at will.

import {setGlobalImmer} from 'use-immer-reactn';
const changeTitleProducer = ( originalTitle ) => {
    originalTitle.en += ' Changed';
};
setGlobalImmer( 'title', changeTitleProducer );

Simplified

setGlobalImmer( 'title', originalTitle => {
    originalTitle.en += ' Changed';
} )

Using entire global state

The passed function works exactly the same as a "producer" in Immer. Receiving the entire state (the same way setGlobal in ReactN does) as it's only parameter which may be mutated at will.

import {setGlobalImmer} from 'use-immer-reactn';
const changeTitleProducer = ( original ) => {
    original.title.en += ' Changed';
};
setGlobalImmer( changeTitleProducer );

Simplified

setGlobalImmer( 'title', original => {
    original.title.en += ' Changed';
} )

setGlobalImmerProvider

Use when working with a custom provider created by createProvider.

Works very similar to setGlobalImmer except it accepts a Provider as the first argument.

import {createProvider} from 'reactn';
import {setGlobalImmerProvider} from 'use-immer-reactn';

export const Provider = createProvider( {
    title: {
        en: 'Hello World'
    }
} )

const changeTitleProducer = originalTitle => {
    originalTitle.en += ' Changed';
};
setGlobalImmerProvider( Provider, 'title', changeTitleProducer );

Simplified

setGlobalImmerProvider( Provider, 'title', title => {
    title.en += ' Changed';
} )

TypeScript Support

Use Immer ReactN supports TypeScript out of the box! It is written entirely in TypeScript. This gives it powerful intellisense, auto-complete, and error-catching abilities.

While there is not configuration required to use this package, there is one caveat passed down from ReactN which requires you to setup a src/global.d.ts file to tell TypeScript the shape of your global state.

If you are already using TypeScript with ReactN, odds are good you have already gone through the steps outlined here. If not, you'll likely want to do so.