-
Notifications
You must be signed in to change notification settings - Fork 670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run selectors twice in development to warn for memoization failures #611
Comments
Basically following the React StrictMode logic - run everything twice to reveal issues, 😞 even if it might create some issues. Might be it's better to first implement it in |
We've got a proof-of-concept PR up that does this. Biggest questions:
|
I think this is a great idea, but I think it should absolutely be opt in like react's strict mode checks. I could see it causing a lot of unnecessary bug reports from people that didn't know the feature was coming, |
I don't see what bug reports would be raised? The change means that a warning is logged if (and only if) any of the input selectors return a different reference when called with the same arguments. Input selectors should never have side effects, so I don't see it as equivalent to StrictMode. Invoking input selectors twice should only at worst impact performance in non-production environments. |
Fair enough. I guess I'm just having flashbacks the strict mode update where tons of libraries were getting bug reports that were in-app problems but they didn't realize and library maintainers had to deal with all that haha. But you're right this is a different problem set so as long as the messaging is clear and it's optional somehow it should be fine either way |
currently i've enabled opting out via the CreateSelectorOptions: const selector = createSelector([...inputs], output, { inputStabilityCheck: false }); this could get inconvenient if you wanted to disable it for an entire set of selectors, so it may be worth seeing if createSelectorCreator's signature can be revised in a way that allows for passing a config object. edit: I've removed the per selector config in favour of a lib level flag: import { setInputStabilityCheckEnabled} from 'reselect'
setInputStabilityCheckEnabled(false)
// now disabled
setInputStabilityCheckEnabled(true)
// enabled again i think the chances of a user wanting the check for some selectors and not for others is essentially nil. |
Let's first split the use cases:
Also, the end user might want to configure a warning or an error - it depends on the end-user and the platform should delegate such a decision to them. |
I've added back the per selector config, and added a "once" option which is now the default - meaning the check is only done on the first run of the selector. This seems like a nice middle ground, which will catch most badly written input functions.
@theKashey Could you give an example? I can't think of a situation where an input selector returning a new reference every time the selector is run would be a good thing, as it would completely blow out the cache every time. Additionally, I can't see a situation where having side effects in an input selector is at all advisable. Selectors should be entirely pure. |
The idea is great, but please let it be opt-in. I know that using poorly optimized projects as examples is not ideal, but they do exist, and in such cases |
@mitroc I've updated the README in the PR's branch - does that make the idea clearer? I don't really understand the argument that projects using bad practices mean that checks to assist developers in following better practices should be opt in. Like I've said, it's simple to disable the check globally, or per selector. The default behaviour only runs the check the first time a selector is used, so I imagine this shouldn't hinder performance significantly past first load of a feature. |
While I do think it is a very good idea to run selectors twice in development to detect improperly memoized selectors, I feel like (at least for React) that it should be done in |
That could also be done, feel free to raise an issue in the react-redux repo suggesting it. |
This one has been asked about for a while, particularly by @theKashey :
The idea is that users sometimes end up writing badly-written selectors that accidentally recalculate the results every time. This is primarily due to badly-written input functions, such as:
Since the input function always returns a new object, the output function will always run and return a new reference.
Probably the simplest thing we can do here would be to double-run the input functions twice and verify that the results are shallow equal.
The text was updated successfully, but these errors were encountered: