hookstate
hookstate copied to clipboard
Resource leak with `useHookstate`
onDestroy
is not called for every onCreate
/ onInit
, resulting in the associated resources not being reclaimed. This happens when a component is instantiated multiple times and may be related to React Strict Mode.
Steps to reproduce:
- Open the example here or use the code from below.
- Click the button repeatedly and see how the number of Hookstate instances goes to infinity.
Code:
import React from "react";
import { useHookstate, hookstate } from "@hookstate/core";
export default function App() {
const component = useHookstate(true);
const count = useHookstate(instanceCounter);
return (
<div className="App">
<button onClick={() => component.set((c) => !c)}>Click</button>
{component.get() ? <h1>Component 1</h1> : <Component />}
Number of Hookstate instances for `state`: {count.get()}
</div>
);
}
function Component() {
const state = useHookstate(2, countInstanceExtension);
return <h1>Component {state.get()}</h1>;
}
const countInstanceExtension = () => ({
onInit: () => {
// setTimeout is to avoid setting counter while rendering.
setTimeout(() => instanceCounter.set((x) => x + 1));
},
onDestroy: () => {
setTimeout(() => instanceCounter.set((x) => x - 1));
},
});
let instanceCounter = hookstate(0);
Hi, very interesting. Hookstate can handle strict mode and can do the related double init/destroy. It seems like it is definitely caused by the strict mode.
I have debugged it. It happens only in StrictMode in development. The fix is possible but may affect extensions callbacks calls behavior. I will try to implement something.