React SDK provider should just be a context provider with its own useOptimiselyContext hook for getting and setting context. If setting the client and user id were separated either with their own functions or even when initialising context somehow, the provider should be able to exist without client being populated so if something goes wrong we can set it later. This will also prevent any rehydration issues with SSR and browser renders, if client fails or user id isn't ready.
import React, {
FC,
useState,
createContext,
useContext,
Dispatch,
SetStateAction,
} from "react";
import { ReactSDKClient } from "@optimizely/react-sdk";
export type OptimizelyContextStateType = {
optimizely: ReactSDKClient | null;
isServerSide: boolean;
timeout: number | undefined;
};
const defaultState: OptimizelyContextStateType = {
optimizely: null,
isServerSide: false,
timeout: 0,
};
export type OptimizelyContextProviderType = [
OptimizelyContextStateType,
Dispatch<SetStateAction<OptimizelyContextStateType>>
];
export const OptimizelyContext = createContext<OptimizelyContextProviderType>([
{ ...defaultState },
() => {},
]);
export const useOptimizelyContext = () => useContext(OptimizelyContext);
export const OptimizelyContextProvider: FC = ({ children }) => {
const [state, setState] = useState({
...defaultState,
});
return (
<OptimizelyContext.Provider value={[state, setState]}>
{children}
</OptimizelyContext.Provider>
);
};
you would then know it's totally safe to wrap your app in the provider because it just stores variables
any other file could do this sort of thing:
import { useOptimizelyContext } from "@optimizely/react-sdk";
const [optimizelyContext, setOptimizelyContext] = useOptimizelyContext();
const { optimizely } = optimizelyContext;
if (optimizely) {
const user: UserType = {blah blah}
optimizely.setUser(user)
}
// or when initialising
try {
const client = await setUpClient();
setOptimizelyContext({ ...optimizelyContext, optimisely: client })
} catch (err) {
}