3.1.2 • Published 9 months ago

@witivio_teamspro/use-reducer v3.1.2

Weekly downloads
-
License
ISC
Repository
-
Last release
9 months ago

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")();
}
3.1.2

9 months ago

3.1.1

9 months ago

3.1.0

1 year ago

3.0.0

1 year ago

2.6.4

2 years ago

2.6.3

2 years ago

2.6.2

2 years ago

2.6.1

2 years ago

2.6.0

2 years ago

2.5.4

2 years ago

2.5.3

2 years ago

2.5.2

2 years ago

2.5.1

2 years ago

2.5.0

2 years ago

2.4.5

2 years ago

2.4.4

2 years ago

2.4.3

2 years ago

2.4.2

2 years ago

2.4.1

2 years ago

2.4.0

2 years ago

2.3.2

2 years ago

2.3.1

2 years ago

2.3.0

2 years ago

2.2.0

2 years ago

2.1.0

2 years ago

2.0.4

2 years ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.2.5

2 years ago

1.2.4

2 years ago

1.2.3

2 years ago

1.2.2

2 years ago

1.2.1

2 years ago

1.2.0

2 years ago

1.1.0

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago