Skip to content

stale closure problem with select option #1639

@TkDodo

Description

@TkDodo

Describe the bug

The select option function is only executed if data (the input to that function) changes. We can see this here, the previous select result is used if the result data hasn't changed:

https://github.com/tannerlinsley/react-query/blob/2de2a0dc322fed60648b4294a613189f967f1f91/src/core/queryObserver.ts#L378-L389

But if you have any other dependency from a closure to that select function, it will not be executed even though a "dependency" to it changes.

To Reproduce

https://codesandbox.io/s/serverless-cdn-3besp?file=/src/index.js

  1. Click on the button, which will increment the count
  2. count is used in the select function, but it is not executed

Expected behavior
select to be executed on every render

Desktop:

  • OS: macOS Catalaina
  • Browser: chrome
  • Version: 3.5.12

Additional Context

Another interesting fact seems to be that we are dependent on the data of the observer (this.currentResult), which means that if you unmount your component, it will execute the selector again, even though we still have data in the cache. See https://codesandbox.io/s/magical-currying-jo0j9?file=/src/index.js

  • click the Inc button, nothing happens
  • click Remount -> select now executes.

This can happen when you do route changes for example. It's a bit undeterministic when the selector function actually runs, so I think it would be better to err on the side of caution and always re-run it. The optimization of not running the selector function in some situations seems a bit premature, If I'm not mistaken, redux also runs the selector on every render, and the suggested solution would be to memoize selectors yourself, e.g. with reselect. Usually, running the selectors is not very expensive.

@boschni FYI

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions