3.1.0 • Published 4 months ago

@witivio_teamspro/use-reducer v3.1.0

Weekly downloads
-
License
ISC
Repository
-
Last release
4 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.0

4 months ago

3.0.0

4 months ago

2.6.4

6 months ago

2.6.3

6 months ago

2.6.2

6 months ago

2.6.1

7 months ago

2.6.0

7 months ago

2.5.4

8 months ago

2.5.3

8 months ago

2.5.2

8 months ago

2.5.1

8 months ago

2.5.0

8 months ago

2.4.5

8 months ago

2.4.4

8 months ago

2.4.3

8 months ago

2.4.2

8 months ago

2.4.1

8 months ago

2.4.0

8 months ago

2.3.2

8 months ago

2.3.1

8 months ago

2.3.0

8 months ago

2.2.0

8 months ago

2.1.0

9 months ago

2.0.4

9 months ago

2.0.3

9 months ago

2.0.2

9 months ago

2.0.1

9 months ago

2.0.0

9 months ago

1.2.5

10 months ago

1.2.4

10 months ago

1.2.3

10 months ago

1.2.2

10 months ago

1.2.1

10 months ago

1.2.0

10 months ago

1.1.0

10 months ago

1.0.6

10 months ago

1.0.5

10 months ago

1.0.4

10 months ago

1.0.3

10 months ago

1.0.2

10 months ago

1.0.1

10 months ago

1.0.0

11 months ago