Skip to content

Leak in useFlag #90

Closed
Closed
@david-bezero

Description

@david-bezero

Describe the bug

the useEffect call in useFlag registers listeners on the client but has no teardown defined. This means that over time, as components which check flag statuses are added and removed, the number of listeners will increase, gradually increasing memory use and reducing app performance (and causing react to complain about "setState called on unmounted component" whenever the flag changes after a component has unmounted).

useEffect(() => {
if (!client) return;
client.on('update', () => {
const enabled = isEnabled(name);
if (enabled !== flagRef.current) {
flagRef.current = enabled;
setFlag(!!enabled);
}
});
client.on('ready', () => {
const enabled = isEnabled(name);
setFlag(enabled);
});
}, [client]);

Steps to reproduce the bug

const Thing = () => {
  const flag = useFlag('foo');
  return null;
};

const App = () => {
  // some rough example code which will display the component for 1 second, then remove it
  const [show, setShow] = useState(true);
  useEffect(() => { setTimeout(() => setShow(false), 1000); }, []);

  return <FlagProvider config={{/*blah*/}}>{show && <Thing />}</FlagProvider>;
};

If the foo flag changes after the component disappears, a warning about calling setState on an unmounted component will appear in the console (once the client refreshes).

Expected behavior

registered listeners should be removed in useEffect's teardown

Logs, error output, etc.

No response

Screenshots

No response

Additional context

No response

Unleash version

No response

Subscription type

No response

Hosting type

No response

SDK information (language and version)

proxy-client-react

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpinned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions