launchdarkly / react-client-sdk

LaunchDarkly Client-side SDK for React.js
Other
86 stars 68 forks source link

Using asyncWithLDProvider outside of the render method #185

Closed doronrosenberg closed 1 year ago

doronrosenberg commented 1 year ago

Describe the bug I have an odd requirement where I need to fetch the LD client id from a REST API which means that my react app renders a loading screen, loads the LD client id and then wants to init the LDProvider component:

  1. Render Loader.tsx
  2. Loader.tsx does an fetch in an useEffect to get the LD client id.
  3. Once the key has been retrieved, Loader.tsx renders a asyncWithLDProvider and the actual app as a child:
export function AppLoader(): JSX.Element {
  const [isInitialized, setIsInitialized] = useState(false);
  const LDProvider = useRef<JSX.Element>(<></>);

  useEffect(() => {
     // load the LD client id and await it
     const provider = await asyncWithLDProvider({
       clientSideID: ldClientId,
       options: {streaming: true},
     });

     LDProvider.current = provider;

     setIsInitialized(true);
  }, []);

  if (!isInitialized) {
    return <>Loading...</>;
  }

  return (
    <LDProvider.current>
      <App />
    </LDProvider.current>
  )
}

However, when App first renders and uses the useFlags() hook, the flags are not initialized and the flags object is empty. After a short time the flags are correctly set. This means the UI flickers as flags are loaded even when using asyncWithLDProvider outside the initial render method.

Is this possible to achieve with the React SDK?

thanks!

To reproduce See above pseudo code.

Expected behavior I would expect the Provider to already have the correct flags loaded by the time the await is finished.

Logs If applicable, add any log output related to your problem.

SDK version 2.27.0

louis-launchdarkly commented 1 year ago

Hello @doronrosenberg, Thank you for reaching out, and sorry for the late reply.

Typically, to avoid flicker, we would recommend using the SDK bootstrapping feature https://docs.launchdarkly.com/sdk/features/bootstrapping I am not sure the local storage option would work, because the device doesn't even know which LD environment it will use until the code is already running. I assume there is a server that serves the React JS to the browser, and maybe you can bootstrap at the point (if you can do the same API query for the client id on your server)?