@witivio_teamspro/use-reducer
TypeScript icon, indicating that this package has built-in type declarations

3.1.0 • Public • Published

React useMagicReducer custom hook


Advantages compared to original useReducer hook

  • Immutable state : you can't update state manually, you have to use dispatch function.
  • No need to create types for reducer methods.
  • You can choose to render or not component when set state (render by default).
  • Access state and reducer functions of your component from top components.
  • The function setState allows to update state partially.
  • No need to create handlers, dispatch method can be called with a closure.

Example of usage

import React, {ReactElement} from "react";
import {MagicReducerObject, MagicReducerRef, useMagicReducer, useMagicReducerRef} from "@witivio_teamspro/use-reducer";

export type State = {
    isOpen: boolean,
    message: string,
}

export type Props = {
    externalRef: MagicReducerExternalRef<typeof reducer>,
}

export type DialogRef = Props["externalRef"];

export const Dialog = (props: Props): ReactElement | null => {
    const [state, dispatch] = useMagicReducer(reducer, initialState, props.externalRef);

    const style: CSSProperties = {
        display: state.isOpen ? "flex" : "none",
        position: "absolute",
        top: "50%",
        left: "50%",
        transform: "translate(-50%, -50%)",
        backgroundColor: "white",
        width: "200px",
        height: "200px",
        flexDirection: "column",
        color: "black"
    }

    return (
        <div style={style}>
            <button onClick={dispatch("close")}>Close X</button>
            {state.message}
        </div>
    )
}

export const initialState: State = {
    isOpen: false,
    message: "",
}

export const reducer = {
    open: ({setState}, [event]: [React.SyntheticEvent | undefined], message: string) => {
        event?.stopPropagation();
        setState({isOpen: true, message});
    },
    close: ({setState}) => {
        setState({isOpen: false});
    }
} satisfies MagicReducerObject<State>;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const TopComponent = () => {
    const dialogRef = useMagicReducerRef(Dialog);

    return (
        <div>
            <Dialog externalRef={dialogRef}/>
            <button onClick={dialogRef.dispatch("open", "Hello world")}>
                Open dialog
            </button>
        </div>
    )
}

How to use props inside reducer functions ?

You just need to create a function for the reducer and pass props as argument, instead of having a simple object.

Here is an example:

export const Dialog = (props: Props): ReactElement | null => {
    const [state, dispatch] = useMagicReducer(reducer(props), initialState, props.externalRef);
    //...
}

export const reducer = (props: Props) => ({
    //...
    logProps: () => {
        console.log(props)
    }
}) satisfies MagicReducerObject<State>;

How to type correctly dispatch method in a pure function ?

Use the type MagicDispatch<typeof reducer> to type correctly the dispatch function.

Here is an example:

import {MagicDispatch} from "@witivio_teamspro/use-reducer";

const myFunction = (dispatch: MagicDispatch<typeof reducer>) => {
    dispatch({type: "logProps"});
}

How to type correctly magic reducer reference in a pure function ?

Use the type MagicReducerRef<typeof Component> to type correctly the reference.

Here is an example:

import {MagicReducerRef} from "@witivio_teamspro/use-reducer";

const myFunction = (dialogRef: MagicReducerRef<typeof Dialog>) => {
    dialogRef.dispatch("open")();
}

Readme

Keywords

none

Package Sidebar

Install

npm i @witivio_teamspro/use-reducer

Weekly Downloads

6

Version

3.1.0

License

ISC

Unpacked Size

41.1 kB

Total Files

11

Last publish

Collaborators

  • nicolashwit
  • yannisdoublet
  • qpla
  • jimmy.king.witivio
  • witivio