How about using createSlice locally, within components, possibly with useReducer to alleviate prop drilling issues? I reckon it'd work much like useReducer itself, except with all the goodness the Toolkit provides. Has somebody thought of such a use case? Are there any reasons why I should not do so?
// This is not needed, but with a factory function we get to export the type
const createContactsBrowserSlice = () => createSlice(/* code here */);
export type ContactsBrowserSlice = ReturnType<createContactsBrowserSlice>;
const ContactsBrowser = () => {
// we can extract this into a hook
const slice = useLazyRef(createContactsBrowserSlice);
const [state, dispatch] = useReducer(slice.current.reducer);
return <SomeComponent contactsBrowserDispatch={disaptch} contactsBrowserState={state}></SomeComponent>
}
Yep, you can absolutely use reducers generated by createReducer and createSlice with React's useReducer hook. I've done it several times myself.
That's one of the nice things about reducer functions. They don't have any direct dependency on Redux in and of themselves, they're just functions. Even when using something like RTK, you could use a reducer with both a Redux store and useReducer.
I am a bit confused what you're doing there with the createContactsBrowserSlice bit. Why does that need to be lazily? Creating a slice should be a one-time thing. If you really need its type, I _think_ you can just do:
const createContactsBrowserSlice = createSlice({/* */});
export type ContactsBrowserSlice = typeof createContactsBrowserSlice;
@markerikson
Your solution will make the slice global (so, basically, we're back to using Redux, I think?). The one I provided will allow every instance of the component to have its own slice, while also keeping it typed.
There's no such thing as a "global slice". A slice is an object containing a set of functions. There's no "instances". You only need to call createSlice once for any given reducer function + actions that you're trying to define.
You can pass the exact same someSlice.reducer function to as many useReducer hooks as you want, in as many components as you want. Each component will have its own copy of the state from each useReducer hook, because that's how React already handles state. But, they can all use the same reducer function reference.
Also, the type of the slice object is static as well. That will never change.
@markerikson
Ah, correct. Awesome. For whatever reason, I had the idea slices do something to keep their state.
Thanks!
Yeah, that's the whole point of reducer functions in the first place :) They're "stateless", in the "not like a class instance" sense. That's why state is the first arg.
Any advice on how to overcome type errors when attempting to use action creators created via createAsyncThunk?
Argument of type 'AsyncThunkAction<{ stuff: any; beep: string; }, any, {}>' is not assignable to parameter of type 'AnyAction'.
Property 'type' is missing in type 'AsyncThunkAction<{ stuff: any; beep: string; }, any, {}>' but required in type 'AnyAction'.ts(2345)
@tkambler : see https://github.com/reduxjs/redux-toolkit/issues/485 (but also note that that really has nothing to do with this closed issue).
Most helpful comment
Yeah, that's the whole point of reducer functions in the first place :) They're "stateless", in the "not like a class instance" sense. That's why
stateis the first arg.