useContext is undefined

Wrapped in a function with a throw, and it throws an error no matter what I've verified it's wrapped in a provider, and the context set-up is identical to the other providers
const SaveButton: Component<JSX.HTMLAttributes<HTMLDivElement>> = (props) => {
const ctx = useSettingsContext();
// rest of code...
const SaveButton: Component<JSX.HTMLAttributes<HTMLDivElement>> = (props) => {
const ctx = useSettingsContext();
// rest of code...
It's not even being used, simply calling the function throws the error This is the context set-up:
type SettingsContextType = {
savedSettings: Settings;
setSavedSettings: SetStoreFunction<Settings>;
settings: Settings;
setSettings: SetStoreFunction<Settings>;
};
const SettingsContext = createContext<SettingsContextType>();
export const useSettingsContext = () => {
const context = useContext(SettingsContext);
console.log(SettingsContext);
if (!context)
throw new Error("useSettings must be used within a SettingsProvider");
return context;
};
type SettingsContextType = {
savedSettings: Settings;
setSavedSettings: SetStoreFunction<Settings>;
settings: Settings;
setSettings: SetStoreFunction<Settings>;
};
const SettingsContext = createContext<SettingsContextType>();
export const useSettingsContext = () => {
const context = useContext(SettingsContext);
console.log(SettingsContext);
if (!context)
throw new Error("useSettings must be used within a SettingsProvider");
return context;
};
Every time I log at all stages nothing is null or not working, SettingsContext seems to be defined fine, but useContext breaks and returns undefined It's wrappped in a provider in the global app I'm not super experienced with context, is there something I'm missing? Is it the fact that the value is an object?
16 Replies
peerreynders
peerreynders2w ago
is there something I'm missing?
Where is the Provider code? I wouldn't describe it as “so simple that it can't possibly break”.
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
const DashboardProvider: Component<DashboardLayoutProps> = (props) => {
const { children, ...rest } = props;

return (
<SettingsProvider>
<LocaleProvider>
<ThemeProvider>
<DashboardLayout {...rest}>
{children}
</DashboardLayout>
</ThemeProvider>
</LocaleProvider>
</SettingsProvider>
);
};
const DashboardProvider: Component<DashboardLayoutProps> = (props) => {
const { children, ...rest } = props;

return (
<SettingsProvider>
<LocaleProvider>
<ThemeProvider>
<DashboardLayout {...rest}>
{children}
</DashboardLayout>
</ThemeProvider>
</LocaleProvider>
</SettingsProvider>
);
};
I just assumed so since it's identical to all my other providers, sorry. Destructuring the children props here or not made no diff
REEEEE
REEEEE2w ago
Where are you using the useSettingsContext and when do you experience the error?
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
In the segment for the SaveButton component Nowhere else To clarify console logging the result of calling useContext returns undefined even in the wrapper, it doesn't really seem to matter I'm not positive the issue lies strictly here but I don't see anyone talking about other code that typically causes context errors as a second order effect
REEEEE
REEEEE2w ago
Okay so some of the cases where it could be undefined are: - Used useContext inside an event handler - Initiated/created the component outside the provider - During hmr in some cases Is the SaveButton used in the props for DashboardProvider?
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
Yes, the dashboard provider is the wrapper I use for all dashboard routes The SaveButton is currently the only child of the settings page route
export const SettingsProvider: Component<{ children: JSX.Element }> = (
props,
) => {
const [savedSettings, setSavedSettings] = makePersisted(
createStore<Settings>(defaultSettings),
PERSISTENCE_OPTIONS,
);
const [settings, setSettings] = createStore<Settings>(savedSettings);

return (
<SettingsContext.Provider
value={{ savedSettings, setSavedSettings, settings, setSettings }}
>
{props.children}
</SettingsContext.Provider>
);
};
export const SettingsProvider: Component<{ children: JSX.Element }> = (
props,
) => {
const [savedSettings, setSavedSettings] = makePersisted(
createStore<Settings>(defaultSettings),
PERSISTENCE_OPTIONS,
);
const [settings, setSettings] = createStore<Settings>(savedSettings);

return (
<SettingsContext.Provider
value={{ savedSettings, setSavedSettings, settings, setSettings }}
>
{props.children}
</SettingsContext.Provider>
);
};
This is the settings context provider Logging it, it initializes everything properly, the value being passed isn't null But just incase somehow something is going wrong here
REEEEE
REEEEE2w ago
Where is DashboardProvider being used It could be that the route isn't able to access it because it's not wrapping it
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
File based routing as the layout for a route group I think you are onto something though because thinking about it, the global layout components such as the theme dropdown and others are able to access their context just fine But the settings provider that's created in the dashboard provider still shows the useContext result as null when I log it there Atleast in the wrapper but I can try to log it in the component Still undefined
REEEEE
REEEEE2w ago
Is it undefined in the route?
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
Yes Undefined everywhere regardless
REEEEE
REEEEE2w ago
I think if the route(s) aren't wrapped properly it's going to be undefined Also just make sure you don't destructure props
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
I mean useContext is undefined no matter what everywhere
Brendonovich
Brendonovich2w ago
Yeah destructuring like here is a surefire way to get problems like this, even if it’s not the cause in this case
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
is it OK to just use splitProps everywhere then as a standard way to get props?
Brendonovich
Brendonovich2w ago
splitProps is fine, but then don’t destructure the objects you get from that either So LocaleProvider and ThemeProvider are both accessible from SaveButton?
ⱼ ₒ ₑ
ⱼ ₒ ₑOP2w ago
Let me see that I think the destructuring at the top level was causing the issue I believe it's working now Thank you all for your help I appreciate it The theme and locale was fine because they weren't children Passed prop children

Did you find this page helpful?