I have a react and next project which uses multiple pages with a similar structure. In each page we are using custom hooks to load data, so it looks something like:
const theme = useTheme()
const router = useRouter()
const { state, dispatch } = useContext(Context)
const { config, metaData } = router.query
const getQueryPath1 = router.query.path1
const getQueryPath2 = router.query.path2
const { siteConfig } = useSiteConfig()
const { partnerAgency } = usePartnerAgency(siteConfig?.agency_prop)
const { partnerParameters } = usePartnerParameters()
const { forms } = useForms(partnerParameters, metaData)
const environment = useEnvironment()
and so on.
As we are using much of these hooks/configs across multiple components (actually next.js 12 pages) I wondered if there was a strategy for combining these under one parent or umbrella hook. This of course feels like it very much goes against the intended usage of hooks, but there must be a way to reduce repetition in the code.
I have tried to create a custom component which would utilize all these hooks but it ended up being not very configurable, and didn’t have the intended outcome of reducing repetition.
Any advice would be appreciated – thanks in advance.
2
Answers
You could move all common hooks into a custom hook to de-clutter you page components and to make the whole declaration shebang re-usable.
usage
But this is not a silver bullet; I usually only put things together in a custom hook that have strong cohesion – this is not the case here, they are really rather unrelated and only have one thing in common: to usually all be used by your typical page component.
And be aware that this reduces flexibility for you; with this approach you cannot omit a hook that’s not really needed on a page, or swap out the form hook for example.
And it is also quite unwieldy with its 12 properties.
I probably would just accept that most page components will have a copy-and-pasted block of hook delarations at the very top. Maybe even sourround it with a comment bracket to clearly show this block is shared.
You should combine code with a single purpose into a custom hook. The main idea is to encapsulate the implementation details, and thus avoid the repetition.
However, combining unrelated logic to a single hook just to avoid repetition, would make your code inflexible. Anytime you’ll need to change anything inside the master hook, you’ll need to go over all your pages to adapt.
From what I can see from your logic, you can extract 2 common hooks.
Hook 1 –
useRouting
:Hook 2 –
useForms
:Now you can use the domain specific hooks in your components: