'wrap useDispatch and useAppSelector with custom hooks
I have following functions and components in my project:
store.ts :
import { combineReducers, createStore } from 'redux';
import { configureStore } from '@reduxjs/toolkit';
import { authDialogReducer } from './authentication/authenticationReducer';
import { toastReducer } from './toast/toastReducer';
const rootReducer = combineReducers({
authDialog: authDialogReducer,
toast: toastReducer
})
export const store = configureStore({
reducer: rootReducer
})
export type AppState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
hooks.ts :
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import { AppDispatch, AppState } from './store';
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<AppState> = useSelector;
Suppose in my project from one of my components which is called AuthDialog I want to use useDispatch and dispatch a action like this:
const AuthDialog: React.FunctionComponent<AuthDialogProps> = (props) => {
const authDialogState = useAppSelector((state) => state.authDialog);
const dispatch = useAppDispatch();
const dispatchAuthDialog = (isOpen: boolean) => {
dispatch({ payload: { isOpen: isOpen }, type: TOGGLE_AUTH_DIALOG } as ToggleAuthDialog)
};
const onCloseDialogClick = () => {
dispatchAuthDialog(false);
}
const onSubmitClick = (e: React.MouseEvent<HTMLElement>) => {
}
const onTabChange = (e: React.ChangeEvent<{}>, newValue: number) => {
}
return <Dialog className={Classes.Root} open={authDialogState.isOpen}>
<DialogContent className={Classes.Content}>
<div className={Classes.AuthDialogIcon}>
<LockOpen />
</div>
<AuthDialogTabs onTabChange={onTabChange} />
</DialogContent>
<DialogActions>
<ButtonGroup>
<CommonButton color="danger" onClick={onCloseDialogClick} title="خروج" />
<CommonButton color="success" onClick={onSubmitClick} title="ثبت" />
</ButtonGroup>
</DialogActions>
</Dialog>
}
If I want to call TOGGLE_AUTH_DIALOG action in everywhere that is used, I should repeat these line of codes:
const authDialogState = useAppSelector((state) => state.authDialog);
const dispatch = useAppDispatch();
const dispatchAuthDialog = (isOpen: boolean) => {
dispatch({ payload: { isOpen: isOpen }, type: TOGGLE_AUTH_DIALOG } as ToggleAuthDialog)
};
So I decided to make it better and instead of repeating mentioned codes, create a hook for each every action that I want to dispatch like:
export const useAuthDialog: () => readonly [AuthDialogState, (isOpen: boolean) => void] = () => {
const authDialogState = useAppSelector((state) => state.authDialog);
const dispatch = useAppDispatch();
const dispatchAuthDialog = (isOpen: boolean) => {
dispatch({ payload: { isOpen: isOpen }, type: TOGGLE_AUTH_DIALOG } as ToggleAuthDialog)
};
return [authDialogState, dispatchAuthDialog] as const;
}
After I did, AuthDialog would be changed to:
const AuthDialog: React.FunctionComponent<AuthDialogProps> = (props) => {
const [authDialogState, toggleAuthDialog] = useAuthDialog();
const onCloseDialogClick = () => {
toggleAuthDialog(false);
}
const onSubmitClick = (e: React.MouseEvent<HTMLElement>) => {
}
const onTabChange = (e: React.ChangeEvent<{}>, newValue: number) => {
}
return <Dialog className={Classes.Root} open={authDialogState.isOpen}>
<DialogContent className={Classes.Content}>
<div className={Classes.AuthDialogIcon}>
<LockOpen />
</div>
<AuthDialogTabs onTabChange={onTabChange} />
</DialogContent>
<DialogActions>
<ButtonGroup>
<CommonButton color="danger" onClick={onCloseDialogClick} title="خروج" />
<CommonButton color="success" onClick={onSubmitClick} title="ثبت" />
</ButtonGroup>
</DialogActions>
</Dialog>
}
Finally, I want to know that this kind of changes can affect the performance of my code? Is it a good thing or not? Because when I have a lots of custom hooks, getting state from useAppSelector is repeating and If I want to use multiple hook in the components, I should write something like:
const [authDialogState, toggleAuthDialog] = useAuthDialog();
const [toastState, toastDialog] = useSuccessToast();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
