I load my settings from the server:
import { Context, createContext, useEffect, useState } from "react";
export class AppSettings {
buildName: string = '';
authority: string = '';
truthPortalApi: string = '';
environment: string = '';
}
export const AppSettingsContext: Context<AppSettings> = createContext<AppSettings>(null!)
export const AppSettingsProvider: React.FC<{ children: JSX.Element }> = ({ children }) => {
const [settings, setSettings] = useState<AppSettings>(new AppSettings())
useEffect(() => {
fetch(`${window.location.origin}/settings`)
.then(response => response.json())
.then(data => setSettings(data))
}, []);
return (
<AppSettingsContext.Provider value={settings}>
{children}
</AppSettingsContext.Provider>
)
}
and then I use them:
...
export const AuthContext: Context<AuthService> = createContext<AuthService>(null!);
export const AuthProvider: React.FC<{ children: JSX.Element[] }> = ({ children }) => {
let appSettings: AppSettings = useContext<AppSettings>(AppSettingsContext)!;
const [authService, setAuthService] = useState<AuthService>(new AuthService(appSettings));
return (
<AuthContext.Provider value={authService}>
{ children }
</AuthContext.Provider>
);
}
export function useAuth(): AuthService {
return useContext(AuthContext);
}
However, something that uses auth via let auth: AuthService = useAuth();
only gets the inital emty value. It doesn’t get the real value after it’s loaded.
Can this work in React?
2
Answers
The package
oidc-client-ts
seems to be the least broken, but you have to wrap it like this in order to pass in the settings.You are not updating the
authService
whenappSettings
change. This line only sets the initial value once (although it recreates a newAuthService
on each render).You need a
useEffect
to create a newAuthService
whenappSettings
change:In addition, you should avoid creating redundant
AuthService
on each render by using lazy initial values function, which would only create the initialAuthService
on mount:Example: