optimizely / react-sdk

React SDK for Optimizely Feature Experimentation and Optimizely Full Stack (legacy)
https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/javascript-react-sdk
Apache License 2.0
89 stars 36 forks source link

A `useEffect`'s within `useDecision` will flap the auto update listeners on every render. #196

Closed epatey closed 3 months ago

epatey commented 1 year ago

This useEffect will mount and execute on every single render. The root cause is that getCurrentDecision in useDecision is not wrapped in useCallback like it is in the other hooks.

  const getCurrentDecision: () => { decision: OptimizelyDecision } = () => ({
    decision: optimizely.decide(flagKey, options.decideOptions, overrides.overrideUserId, overrideAttrs),
  });

  ...

  useEffect(() => {
    // Subscribe to update after first datafile is fetched and readyPromise is resolved to avoid redundant rendering.
    if (optimizely.getIsReadyPromiseFulfilled() && options.autoUpdate) {
      return setupAutoUpdateListeners(optimizely, HookType.FEATURE, flagKey, hooksLogger, () => {
        setState(prevState => ({
          ...prevState,
          ...getCurrentDecision(),
        }));
      });
    }
    return (): void => { };
  }, [optimizely.getIsReadyPromiseFulfilled(), options.autoUpdate, optimizely, flagKey, getCurrentDecision]);
mikechu-optimizely commented 1 year ago

Thanks for reporting this. I've created a work ticket (FSSDK-9624) to review.

junaed-optimizely commented 3 months ago

This has been addressed already in #273 , and a patch release v3.2.1 is also out with the changes. Closing..