Skip to content

lipemat/use-immer-reactn

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

90 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 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';
				} )} />
		</>
	);
};

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

useGlobalImmerProvider

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';
			} )}/>
		</>
	);
};

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

About

React hooks for using Immer with ReactN

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published