Placement of Context Providers and Routes (Router 10.10)

I have an existing application which uses several context providers for sharing data between routes. My question is where do I place the context providers in relation to the route definitions using SolidJS/Router v10+. Is it acceptable to put context providers above the <Router>? Environment: Electron/SolidJS, <HashRouter> The Solid Router docs state:
2. Provide a root level layout This will always be there and won't update on page change. It is the ideal place to put top level navigation and Context Providers
If I set up like this as suggested by the docs: main.tsx (simplified)
render(() => {
return (
<HashRouter root={App}>
<Route path='/home component={Home} />
<Route path='/search component={Search} />
<Route path='/settings component={Settings} />
</HashRouter>
)}, root);
render(() => {
return (
<HashRouter root={App}>
<Route path='/home component={Home} />
<Route path='/search component={Search} />
<Route path='/settings component={Settings} />
</HashRouter>
)}, root);
app.tsx (simplified)
const App = () => {

// ... various data fetching functions to cache in providers

return (
<Provider>
<AppWindow>
<Nav>
{props.children}
</AppWindow>
</Provider>
)
};
const App = () => {

// ... various data fetching functions to cache in providers

return (
<Provider>
<AppWindow>
<Nav>
{props.children}
</AppWindow>
</Provider>
)
};
5 Replies
Calhistorian
CalhistorianOP10mo ago
I am unable to access provider data in <Nav> or in route children. However, if I wrap the <HashRouter> in the providers it works just fine. Alternatively, I have added another component within <AppWindow> and fetched the context data in that component, but that doesn't work either. Is it ok to leave the providers above the <Router>? Or am I missing something?
lxsmnsyc
lxsmnsyc10mo ago
if you are unable to access it, are you mistakenly destructuring the props?
Calhistorian
CalhistorianOP10mo ago
Thank you for the suggestion. No. Definitely not. Out of habit, I never destructure props. I know there is a lot of unknowns in the post itself, but my main concern is whether its ok to have the providers wrapping the router. The context providers are where I put the Electron IPC renderer handles and cache data from the main process. I thought perhaps maybe some race condition is an issue, but the evidence just isn't there that I can see. It is a data heavy application which is why I am concerned about having the context providers above the router. Interesting, I was just running some tests after doings some refactoring by fetching the provider data in its own component that wraps the <MainWindow> component. app.tsx
return (
<Provider>
<MainWindow> // <-- fetching data inside this component and setting to context stores of the providers.
{props.children}
</MainWindow>
</Provider>
)
return (
<Provider>
<MainWindow> // <-- fetching data inside this component and setting to context stores of the providers.
{props.children}
</MainWindow>
</Provider>
)
So it seems all the context providers are working except one. The logged output in the console is:
> Object <-- provider not working
> Proxy(Object) <-- provider working
> Proxy(Object) <-- provider working
> Proxy(Object) <-- provider working
> Proxy(Object) <-- provider working
> Object <-- provider not working
> Proxy(Object) <-- provider working
> Proxy(Object) <-- provider working
> Proxy(Object) <-- provider working
> Proxy(Object) <-- provider working
Each context is constructed in the exact same way using a Solid Store at its core:
const defaultContext = {...key:values}
const defaultContextValue = [state, methods]
const context = createContext(defaultContextValue)
export const Provider = () => {
const [state, setState] = createStore(defaultContext)
const actions = {
...methods
}
const contextValue = [state, actions]

return (
<Context.Provider value={contextValue}>
{props.children}
</Context.Provider>
)
}

export const useContext = () => useContext(context);
const defaultContext = {...key:values}
const defaultContextValue = [state, methods]
const context = createContext(defaultContextValue)
export const Provider = () => {
const [state, setState] = createStore(defaultContext)
const actions = {
...methods
}
const contextValue = [state, actions]

return (
<Context.Provider value={contextValue}>
{props.children}
</Context.Provider>
)
}

export const useContext = () => useContext(context);
I don't know if this helps, but for completeness for the thread and others down the line. I can't figure out why one provider works and the others do. Each provider plays a very small role -- settings, UI state, user, and some core shared data. 🤷‍♂️
lxsmnsyc
lxsmnsyc10mo ago
Can you provide a working repro that I could test?
Calhistorian
CalhistorianOP10mo ago
I will. Thanks
Want results from more Discord servers?
Add your server