Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No next method or return value in the useReducer + middleware example #233

Closed
dht opened this issue May 3, 2022 · 1 comment
Closed

Comments

@dht
Copy link

dht commented May 3, 2022

In the this example, currently, the middleware does not take in account two important aspects of middlewares:

  1. the next method
  2. the return value mechanism

The next method enables you to break the middleware chain in certain circumstances.
The return value mechanism allows you to bubble up promises or return values to the entity which invoked the dispatch method.

@dht dht changed the title Middleware example No next method or return value in the useReducer + middleware example May 3, 2022
@dht
Copy link
Author

dht commented May 3, 2022

Perhaps something like that:

import { Reducer, useMemo, useReducer } from 'react';

type Json = Record<string, any>;
type Action = { type: string } & Json;
type Middleware = (store: any) => (next: any) => (action: Action) => any;

export function useReducerWithMiddleware<T>(
    reducer: Reducer<any, any>,
    initialState: T,
    middlewares: Middleware[]
) {
    const [state, dispatch] = useReducer(reducer, initialState);

    const mockStore = useMemo(
        () => ({
            dispatch, //
            getState: () => state,
            updateReducer: () => {},
        }),
        [state, dispatch]
    );

    const dispatchWithMiddleware = (action: Action) => {
        let output;

        for (let middleware of middlewares) {
            let nextWasCalled = false;

            const next = () => {
                nextWasCalled = true;
            };

            output = middleware(mockStore)(next)(action) || output;

            if (!nextWasCalled) {
                break;
            }
        }

        dispatch(action);
    };

    return [state as T, dispatchWithMiddleware];
}

Which will make it possible to use the same middlewares redux signature:

const logger = (store: any) => (next: any) => (action: any) => {
    console.log('dispatching', action);
    let result = next(action);
    console.log('next state', store.getState());
    return result;
};

export const Component = (props) => {
    const [state, dispatch] = useReducerWithMiddleware(
       reducer,
        initialState,
        [logger]
    );
//  ...component definition...
}

@dht dht closed this as completed Aug 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant