Have you had a look into using React.Context
to create a global provider (or specifically scoped around your layouts)? This way you could store your actions within a reducer.
hooks/use-context.jsx
import React from 'react'
// Set a relevant initial state
const INITIAL_STATE = {}
// Add actions for your application
const ACTIONS = {
UPDATE_VAR: 'update-var',
DELETE_VAR: 'delete-var'
}
const reducer = (state, action) => {
const next = { ...state } // Shallow copy
switch (action.type) {
case ACTIONS.UPDATE_VAR:
next.var = action.data
break
case ACTIONS.DELETE_VAR:
delete next.var
break
}
return next
}
const Context = React.createContext({
state: { ...INITIAL_STATE },
dispatch: () => null
})
export const Provider = ({ children }) => {
const [state, dispatch] = React.useReducer(
reducer, init(false)
)
return (
<Context.Provider value={[state, dispatch, ACTION]}>
{children}
</Context.Provider>
)
}
// Rename to something relevant
const useContext = () => {
const [state, dispatch] = React.useContext(Context)
return [state, dispatch]
}
export default useContext
pages/index.jsx: Provide state
import { Provider } from '../hooks/use-context'
const Page = () => (
<Provider>
<AppActions />
<AppListings />
</Provider>
)
export default Page
components/app-actions.jsx: Update state
import useContext from '../hooks/use-context'
const AppActions = () => {
const [, dispatch] = useContext()
return (
<button onClick={() => dispatch(/* action */)>
Click Me
</button>
)
}
export default AppActions
components/app-listings.jsx: Consume state
import useContext from '../hooks/use-context'
const AppListings = () => {
const [state] = useContext()
return (
<pre>{JSON.stringify(state, null, 2)</pre>
)
}
export default AppListings
You could also look into third-party solutions such as Redux.