reactjs - omslut useDispatch och useAppSelector med egna hooks
Jag har följande funktioner och komponenter i mitt projekt:
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;
Anta att jag i mitt projekt från en av mina komponenter, som kallas AuthDialog, vill använda useDispatch och dispatcha en åtgärd som denna:
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>
}
Om jag vill kalla på TOGGLE_AUTH_DIALOG-åtgärden överallt där den används, bör jag upprepa dessa kodrader:
const authDialogState = useAppSelector((state) => state.authDialog);
const dispatch = useAppDispatch();
const dispatchAuthDialog = (isOpen: boolean) => {
dispatch({ payload: { isOpen: isOpen }, type: TOGGLE_AUTH_DIALOG } as ToggleAuthDialog)
};
Så jag bestämde mig för att göra det bättre och, istället för att upprepa de nämnda koderna, skapa en hook för varje åtgärd som jag vill skicka, som:
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;
}
Efter att jag gjort det, skulle AuthDialog ändras till:
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>
}
Slutligen, kan den här typen av förändring påverka prestandan i min kod? Är det något bra eller inte? För när jag har många anpassade hooks är det upprepande att hämta state från useAppSelector, och om jag vill använda flera hooks i komponenterna bör jag skriva något som:
const [authDialogState, toggleAuthDialog] = useAuthDialog();
const [toastState, toastDialog] = useSuccessToast();