React hook and helper function for using Immer with ReactN.
npm install use-immer-reactn
oryarn add use-immer-reactn
Assuming your global state set in ReactN looks like this:
{
title: {
en: 'Hello World'
}
}
Works like 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 the same as a "producer" in Immer. Receiving the original value as it's only parameter, which may be mutated at will.
If the current component is nested below a custom provider, the hook will automatically use the custom provider.
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';
} )} />
</>
);
};
Works very similar to setGlobal
in ReactN with two differences:
- An (optional) property may be specified to work with just that key instead of the entire global state.
- A function (producer) is passed instead of the new value.
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';
} )
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';
} )
Use when working with a custom provider created by createProvider
from a component not nested below the provider.
@notice If the current component is nested before the provider, use instead useGlobalImmer
.
type CustomState = {
loading: boolean;
}
const provider = createProvider<CustomState>( {} );
export default () => {
const [ title, setTitle ] = useGlobalImmerProvider<CustomState, 'title'>( provider, 'title' );
return (
<>
<h1>{title.en}</h1>
<button onClick={() => setTitle( draft => {
draft.en += ' Changed';
} )}/>
</>
);
};
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';
} )
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 no 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.