Skip to content
This repository has been archived by the owner on Nov 11, 2023. It is now read-only.

stabilize the identity of useGet and its refetch method #348

Merged
merged 1 commit into from
Apr 22, 2021

Conversation

amacleay-cohere
Copy link
Contributor

Stabilizing the identity of the fetchData function presents some
challenges. The biggest is that fetchData needs to have access to
state and setState, but it needs to have the most up-to-date version
of them in order to work. There are two ways to have done this: the
first is to move the definition of fetchData into the function body of
useGet itself and make it a closure over the state and setState
variables - that is the approach taken here. Alternatively, we could
define fetchData as a function which takes state and setState as
parameters, but is closed over a particular combination of props and
context values - this option wasn't explored.

The end result is that the identity of the refetch function is stable
given a certain set of props and context, and it is stable over a deep
comparison thereof - so both of the following work fine:

const queryParams = { page: 1 };
function MyComponent = () => {
  const { refetch } = useGet({ queryParams, lazy: true })`
  ...
};
function MyComponent = () => {
  const { refetch } = useGet({ { page: 1 }, lazy: true })`
  ...
};

This should resolve #186 fully (I hope!)

Why

Solves #186

NB

There are 3 tests which suffer from the same symptom: for a reason I haven't completely tracked down, there is an extra re-render dispatched by the hook with identical state: in both instances, it is when the re-render is called, there are 2 returns out of the hook with loading: true. I don't suppose this will cause any issues with any callers, but I was unable to totally root it out.

Note that this uses the same useDeepCompareCallback that is also present in #338 - the implementation in either case is identical and could be rebased out safely depending on merge order.

@netlify
Copy link

netlify bot commented Apr 17, 2021

Deploy request for restful-react accepted.

Accepted with commit 3f02d9d

https://app.netlify.com/sites/restful-react/deploys/608096b392ab900008f13730

@fabien0102
Copy link
Contributor

Sorry, I missed the notification, will review this tomorrow!

Just as a sidenote, I did saw this on twitter recently: https://epicreact.dev/the-latest-ref-pattern-in-react/ and of course, I thought about this old issue ^^ This could be neat way to solve this!

src/useGet.test.tsx Outdated Show resolved Hide resolved
src/useGet.test.tsx Outdated Show resolved Hide resolved
await wait(() => expect(children).toBeCalledTimes(3));
expect(children.mock.calls[2][0].loading).toEqual(false);
expect(children.mock.calls[2][0].data).toEqual({ id: 1 });
// A mystery... this is called an extra time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if this not a big issue, a bit of investigation over there could be nice (at least to understand ^^)

Stabilizing the identity of the `fetchData` function presents some
challenges. The biggest is that `fetchData` needs to have access to
`state` and `setState`, but it needs to have the most up-to-date version
of them in order to work. There are two ways to have done this: the
first is to move the definition of `fetchData` into the function body of
`useGet` itself and make it a closure over the `state` and `setState`
variables - that is the approach taken here. Alternatively, we could
define `fetchData` as a function which takes `state` and `setState` as
parameters, but is closed over a particular combination of props and
context values - this option wasn't explored.

The end result is that the identity of the `refetch` function is stable
given a certain set of props and context, and it is stable over a deep
comparison thereof - so both of the following work fine:
```typescript
const queryParams = { page: 1 };
function MyComponent = () => {
  const { refetch } = useGet({ queryParams, lazy: true })`
  ...
};
```

```typescript
function MyComponent = () => {
  const { refetch } = useGet({ { page: 1 }, lazy: true })`
  ...
};
```

This should resolve contiamo#186 fully (I hope!)
Copy link
Contributor

@fabien0102 fabien0102 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, let's ship this!
Thanks again for this amazing contribution! 🎉

@fabien0102 fabien0102 merged commit d34e7e7 into contiamo:master Apr 22, 2021
@amacleay-cohere amacleay-cohere deleted the stabilize-use-fetch branch April 22, 2021 14:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lazy fetching of data will cause infinite loop / runaway effect
2 participants