1
0
Fork 0
freesewing/sites/shared/hooks/use-app.mjs
2023-03-26 08:49:21 +02:00

68 lines
1.7 KiB
JavaScript

import { loadNavigation } from 'site/lib/load-navigation.mjs'
// Hooks
import { useState, useEffect } from 'react'
import { useBugsnag } from 'shared/hooks/use-bugsnag.mjs'
// Dependencies
import get from 'lodash.get'
import set from 'lodash.set'
import unset from 'lodash.unset'
const defaultState = {
loading: false,
modal: null,
menu: {
main: null,
},
}
/*
* The useApp hook
*/
export function useApp(props = {}) {
const { bugsnag = false, page = {}, loadState = {} } = props
const { path = false } = page
if (!path) throw 'You MUST pass a page.path prop to the useApp hook'
const reportError = useBugsnag(props?.bugsnag)
// React state
const [state, setState] = useState(() => ({ ...defaultState, ...loadState }))
useEffect(() => {
// Force update of navigation info (nav, title, crumbs) on each page change
if (path) setState({ ...state, ...loadNavigation(path) })
}, [path, state.slug, state.title])
/*
* Helper methods for partial state updates
*/
const updateState = (path, value) => setState(set({ ...state }, path, value))
const unsetState = (path) => setState(unset({ ...state }, path))
/*
* Helper methods for specific state updates
*/
const closeModal = () => updateState('modal', null)
const closeMenu = (name) =>
get(state, `menu.${name}`, false) ? updateState(`menu.${name}`, false) : null
const startLoading = () => updateState('loading', true)
const stopLoading = () => updateState('loading', false)
return {
// All-purpose React state object
state,
setState,
updateState,
unsetState,
// Helper methods
closeModal,
closeMenu,
startLoading,
stopLoading,
// Bugsnag helper
reportError,
}
}