Skip to content

React.StrictMode causes async action listeners to not be cleaned up properly #60

@a-tonchev

Description

@a-tonchev

Hi, I am using a CRA application, with lazy-loading and react-router-dom.

I am using the createAsyncAction method like this:

const getAllOrders = createAsyncAction(
  async () => {
    const res = await Connections.postRequest('getAllOrders');
    const { orders = [] } = res.data || {};
    if (res.ok) {
      return successResult(orders);
    }

    return errorResult([], `Error on getting orders: ${res.errorMessage}`);
  },
  {
    cacheBreakHook: ({ result, timeCached }) => !result.error
      && timeCached + CachingDurations.ALL_ORDERS < DateHelper.getTimestamp(),
  },
);

with custom updater inside the component:

  const [finished, result, updating] = getAllOrders.useBeckon({ tag: 'allOrders' });

...

  const updateOrders = () => {
    getAllOrders.run(
      { tag: 'allOrders' },
      {
        treatAsUpdate: true,
      },
    );
  };

I want to use the cool caching functionality, but I want also to give the user ability to update by himself the data.

So when I open for first time the route and click on the updateOrders function, it works like a charm. But when I open another page and come back to this orders-route, when I click on updateOrders I get this error message:

index.js:1 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

I debug a little bit and figure out, that somehow the event listeners are not really removed when my component is unmounted, that is in the function notifyListeners:

function notifyListeners(key) {
e thi    if (clientAsyncCache.listeners.hasOwnProperty(key)) {
        for (const watchId of Object.keys(clientAsyncCache.listeners[key])) {
            clientAsyncCache.listeners[key][watchId]();
        }
    }
}

Screenshot_3

as you can see on the pic, I have 3 listeners.

I tryed to reconstruct here the same issue

https://codesandbox.io/s/pullstate-client-only-example-forked-4707o?file=/src/index.tsx

But here it works fine, and the event listeners are just cleared like they should be:

Screenshot_2

as you can see on the picture, all the old event listeners are cleared successfully and there is no such issue.

I am a little bit confused. Is there any option to clean all the previous listeners manually in the useEffect?

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    react-nextIssue related to getting ready for the next iterations of React

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions