Custom Context hooks
Creating a useDispatch
Hook
For starters, we can avoid needed to bring in both the ColorContext
and useContext
hook by creating a useDispatch
hook that brings them both together in an easily digestible format.
export const useDispatch = () => {
const { dispatch } = useContext(ColorContext);
return useMemo(() => dispatch, [dispatch]);
};
And now, we can use that anywhere we might have needed dispatch
out of createContext
.
For example, we can use it in src/components/shared/color-change-swatch.tsx
:
const ColorChangeSwatch = ({ hexColor, className }: ColorChangeSwatchProps) => {
const dispatch = useDispatch();
return (
// …
);
};
If we check out this branch, I've taken the libery of doing two things: filling out the rest of our actions in the reducer. I also created a number of custom hooks that typed for us out of the box.
I'll include them here for convenience.
First of all, we've got out actions:
const colorReducer = (
state: ColorState = initialState,
action: ColorActions,
) => {
if (action.type === 'update-hex-color') {
const { hexColor } = action.payload;
return { ...state, hexColor };
}
if (action.type === 'update-rgb-color') {
const hexColor = '#' + rgb.hex(action.payload.rgb);
return { ...state, hexColor };
}
if (action.type === 'update-hsl-color') {
const hexColor = '#' + hsl.hex(action.payload.hsl);
return { ...state, hexColor };
}
if (action.type === 'update-hsv-color') {
const hexColor = '#' + hsv.hex(action.payload.hsv);
return { ...state, hexColor };
}
if (action.type === 'update-cmyk-color') {
const hexColor = '#' + cmyk.hex(action.payload.cmyk);
return { ...state, hexColor };
}
return state;
};
Next up, let's look at src/hooks.ts
:
import { useCallback, useContext, useMemo } from 'react';
import { ColorContext } from './context';
export const useDispatch = () => {
const { dispatch } = useContext(ColorContext);
return useMemo(() => dispatch, [dispatch]);
};
export const useHexColor = () => {
const { state } = useContext(ColorContext);
return useMemo(() => state.hexColor, [state]);
};
export const useUpdateHexCode = () => {
const dispatch = useDispatch();
return useCallback(
(hexColor: string) =>
dispatch({ type: 'update-hex-color', payload: { hexColor } }),
[dispatch],
);
};
export const useUpdateRGB = () => {
const dispatch = useDispatch();
return useCallback(
(rgb: RGB) => dispatch({ type: 'update-rgb-color', payload: { rgb } }),
[dispatch],
);
};
export const useUpdateHSL = () => {
const dispatch = useDispatch();
return useCallback(
(hsl: HSL) => dispatch({ type: 'update-hsl-color', payload: { hsl } }),
[dispatch],
);
};
export const useUpdateHSV = () => {
const dispatch = useDispatch();
return useCallback(
(hsv: HSV) => dispatch({ type: 'update-hsv-color', payload: { hsv } }),
[dispatch],
);
};
export const useUpdateCMYK = () => {
const dispatch = useDispatch();
return useCallback(
(cmyk: CMYK) => dispatch({ type: 'update-cmyk-color', payload: { cmyk } }),
[dispatch],
);
};