hookstate icon indicating copy to clipboard operation
hookstate copied to clipboard

Resource leak with `useHookstate`

Open zroug opened this issue 1 year ago • 2 comments

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:

  1. Open the example here or use the code from below.
  2. 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);

zroug avatar Mar 17 '23 23:03 zroug

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.

avkonst avatar Mar 19 '23 20:03 avkonst

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.

avkonst avatar Apr 01 '23 22:04 avkonst