@witivio_teamspro/use-reducer v3.1.0
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")();
}
4 months ago
4 months ago
6 months ago
6 months ago
6 months ago
7 months ago
7 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
11 months ago