Feature proposal: isLatest()
See original GitHub issueHey it’s franciscop from this PR on my work account. While isMounted()
works great for requests where you normally go forward/backwards between pages, I think this could also greatly benefit from an isLatest()
, isFresh()
or similar. For this code:
export default ({ userId }) => {
const [user, setUser] = useState(false);
useAsyncEffect(async isMounted => {
const user = await fetch(`/users/${userId}`);
if (!isMounted()) return;
setUser(user);
}, [userId]);
return <div>{user ? user.name : "Loading..."}</div>
};
It’ll not try to set the user on an unmounted component, which is already great and fixing so many issues. But, if the userId
changes, the component will not remount so there’s effectively a race condition and if the second fetch()
finishes before the first one it’ll overwrite the data. If we also had a isLatest
(a superset of isMounted
) this race condition could be avoided:
export default ({ userId }) => {
const [user, setUser] = useState(false);
useAsyncEffect(async (isMounted, isLatest) => {
const user = await fetch(`/users/${userId}`);
if (!isLatest()) return;
setUser(user);
}, [userId]);
return <div>{user ? user.name : "Loading..."}</div>
};
If this feature is welcome, there are three options here:
- Add it as a new parameter:
useAsyncEffect(async (isMounted, isLatest) => ...);
. The problem is thatisLatest()
is a superset ofisMounted()
, so if you are usingisLatest()
thenisMounted()
is not needed. - Release a major version with a new API and named parameters:
useAsyncEffect(async ({ isMounted, isLatest }) => {...});
- Make it a bit hacky to keep both of the above options available. No need for major release, can work as a parameter. Both of these work:
useAsyncEffect(async isMounted => ...)
anduseAsyncEffect(async ({ isMounted, isLatest }) => ...)
I like the last one slightly more, and you can remove the legacy way in the future when there’s a major release. But it’s up to what you prefer 😄
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
One concern I had wass race conditions if we keep a single global active ref, but a plain variable
active
like this would do the trick and won’t suffer from a later useEffect overwriting the previous one, so this looks good.Why not putting it inside
useEffect()
though? Any thoughts?Note: I reviewed my original
isMounted()
, and it had a bug that I misinterpreted as a different bug.Awesome, thanks!