DEV Community

loading...

Discussion on: React Context with useReducer and Typescript.

Collapse
mannguyen0107 profile image
Man Nguyen

Greate post! although I have a question the way you have the type right now with the actions being a Discriminated unions of all the actions that created by ActionMap of all the reducers. This is very hard to manage when you have alot of reducers. There is no separation of concern. How would I go about moving each reducer into its own files. Then would I import each and every actions from all the reducer so I can use discriminated unions? I think there should be a better way, but I'm not knowledgable to do that yet. Do you have any suggestion?

Collapse
elisealcala profile image
Elizabeth Alcalá Author

Thanks! Yes I know if you have more than three reducers the types for the main reducer can increase, and be hard to manage.
I don't know how to improve the action type, this action has to be a union of product and shoppingCart actions because when using dispatch you can use either of both actions. To know exactly what action I need to use, maybe you could try with generics and conditional types. I think you could pass a generic type through Context to enable just certain types for actions and state. It's an idea, maybe works. I'll try to implement it.

Collapse
mannguyen0107 profile image
Man Nguyen

As it turned out your way of doing the combine reducers also works for type-safe all you gotta do is use type assertion ie:

const mainReducer = ({ products, shoppingCart }: InitialStateType, action: ProductActions | ShoppingCartActions) => ({
  products: productReducer(products, action as ProductActions),
  shoppingCart: shoppingCartReducer(shoppingCart, action as ShoppingCartActions),
});
Enter fullscreen mode Exit fullscreen mode

By using the 'as' keyword there you can now get rid of the unions type on the action arg of your reducers

Thread Thread
elisealcala profile image
Elizabeth Alcalá Author

Hey, you are right, type assertion works well in this case, it makes the code look cleaner without the union types.

Thanks a lot.

Collapse
mannguyen0107 profile image
Man Nguyen

So I found this on a stack overflow post

function combineReducers(reducers) {
    return (state = {}, action) => {
        const newState = {};
        for (let key in reducers) {
            newState[key] = reducers[key](state[key], action);
        }
        return newState;
    };
}
Enter fullscreen mode Exit fullscreen mode

all you have to do is pass an object with key and value is the reducer. I'm searching about generic to convert this function to be type-safe. But if you have any idea please share. Thank you!