fix: reduce the number of renders#754
Conversation
|
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/tannerlinsley/react-query/knvumyz9i |
|
Wow, this is a lot to take in all at once. I'll try and get to this asap. |
tannerlinsley
left a comment
There was a problem hiding this comment.
I love these bits where we're just being smarter about dispatching and fixing some of the funky timing issues. I would really like to merge these asap too, since they're non-breaking changes that will help everyone.
On the topic of all of the useBaseQuery and related changes, I'm not sure I'm on board yet with the implementation. I totally agree with you on the problems that need to be solved, but a have a few concerns:
- There's a lot of ref wizardry going on where I feel it could be more of just
useMemowith the right dependencies. - Despite the changes being correctly aligned to the docs now, this would technically be a breaking change. I would like to avoid that at all costs. I'm okay if some of the publicly accessible API is undocumented. When we start considering a v3, we could then actually remove some of the public API to be in line with the docs (or just update the docs :)
- I'm not a fan of increase in library size that this is resulting in. It looks like 0.4kb or something similar. Not crazy, but i would expect that for this size, we're adding some massive features, not fixing some bugs. Which kinda points me to my last point.
- I think this same outcome could be achieved with less code. I'm not sure what that is yet, but I think it can. It might involved stripping away into the core a bit more, which I'm fine with.
I think what I'd like to see happen from this point:
- This PR becomes a subset of the quick wins that I commented on so we can get them merged asap.
- A new PR for the tests that ensure value stability (so we can experiment with the current version and try to get the tests to pass with other implementations
- A sibling PR containing the changes you've made to achieve value stability.
From there I'd like to use that second PR as a jumping off point and take a shot at combining some of the tactics you've implemented in your changes with a few lower level changes I have in mind (but haven't validated) yet.
60b1317 to
c2cfdb5
Compare
c2cfdb5 to
d6cac0c
Compare
|
Happy to help! I have adjusted the PR with these changes:
With these changes the number of renders is still reduced to 2 and I think this is actually a simpler and more performant solution :) But if you have any doubts about the implementation then I don’t mind splitting it up. PS: I removed the |
d6cac0c to
32446c4
Compare
32446c4 to
6765e40
Compare
|
It’s looking better! So do you really think we need the shallow equal? If we are using a reducer we should be able to do an identity check instead, right? |
|
Currently the state always changes when an action is dispatched, regardless of whether some value has actually changed or not. We could add manual checks in the reducer (or before dispatching actions) to prevent this. For example: But this would need to be done in multiple places and is a bit prone to mistakes. Doing a shallow check after the state update is probably the simplest and most bullet-proof solution. |
|
Alright, thats fair. How about we do this instead and just get rid of the shallow equal? // Do nothing if the state did not change
if (deepIncludes(query.state, newState)) {
return
}It passes your tests! ;) |
|
The |
|
Okay. The primary motivation for that suggestion was just bundle size. So I’m good if that’s the only way to do it right.
…On Jul 16, 2020, 10:13 AM -0600, Niek Bosch ***@***.***>, wrote:
The deepIncludes function would be a bit slower because it does a deep comparison (including response data). Also, because it checks if b is a subset of a it does not really check if the objects are equal. One way to solve this would be to run the check two times like deepIncludes(query.state, newState) && deepIncludes(newState, query.state) but that would slow it down even more. Think the shallowEqual function is more suited for the job :)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
|
Can you pull in the latest from master? |
6765e40 to
a6220a0
Compare
|
Updated 👍 |
a6220a0 to
380606d
Compare
380606d to
61edf13
Compare
61edf13 to
8b8ff15
Compare
|
Updated the branch again and removed the |
|
🎉 This PR is included in version 2.5.5 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
@tannerlinsley @boschni Hey folks! I am suspecting this PR caused some regressions in our test suite regarding when update: I am wrong, it was the opposite! This seemed to fix it('should not call query if data is cached', () => {
queryCache.setQueryData('mock', { stale: true });
const mockQueryFn = jest.fn(() => ({ test: true }));
const data = await queryCache.prefetchQuery('mock', mockQueryFn);
expect(mockQueryFn).not.toHaveBeenCalled();
expect(data).toEqual({ test: true });
})Adjusting our stale time for the test will fix the issue, as per the new it('should not call query if data is cached', () => {
- queryCache.setQueryData('mock', { stale: true });
+ queryCache.setQueryData('mock', { stale: true }, { staleTime: 100 });
const mockQueryFn = jest.fn(() => ({ test: true }));
const data = await queryCache.prefetchQuery('mock', mockQueryFn);
expect(mockQueryFn).not.toHaveBeenCalled();
expect(data).toEqual({ test: true });
}) |
Hi there! This PR includes the following changes:
With these changes, the number of renders for successful and unsuccessful queries can be reduced from 4 to 2.
PS: While working on the tests, I noticed the
canFetchMoreandisFetchingMoreproperties are sometimes set toundefined. I guess this is not correct? For now I matched the assertions with the current behaviour.