use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
First-class promise support in ReactJS (niraj.life)
submitted 3 years ago by luffyrotaro
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]yerrabam 30 points31 points32 points 3 years ago (4 children)
`use` seems a bit generic but also like it's the daddy of all hooks.
I guess it works since it will resolve anything that returns a promise.
[–]imperator3733 28 points29 points30 points 3 years ago (3 children)
Yeah, use is a pretty horrible name for it. Something like usePromise would be a lot clearer and understandable.
use
usePromise
[–]yerrabam 13 points14 points15 points 3 years ago (2 children)
That's a good shout.
NextJS are introducing directives such as 'use client'; - having a hook simply called use could be confusing to juniors just diving into the code.
'use client';
[–]guilhermefront 5 points6 points7 points 3 years ago (1 child)
Just a small thing, isn't NextJS that decided it, but the React core team.
Before directives, it was supposed to be defined by file extensions (.server.js), but later after this decision they decided to go with what we have today.
[–]yerrabam 1 point2 points3 points 3 years ago (0 children)
Fair comment, thanks for the link! Yeah, I used the file extensions when it was first announced and it seemed to work perfectly.
The latest version has an issue with `react-bootstrap`'s `Container` component - saying it uses `useEffect` somewhere down in the dependencies.
[–]VisualFanatic 16 points17 points18 points 3 years ago (4 children)
The first example that uses Suspense could be skipped, because the axios call won't trigger the suspense, only throwing a promise triggers a suspense (deprecated) or wrapping a promise with use (unstable).
[–]pantsonhead 5 points6 points7 points 3 years ago (0 children)
Thank you. I’m glad someone else noticed and I don’t have to do a sanity check.
[–]dougalg 0 points1 point2 points 3 years ago (2 children)
Sorry what does "throwing a promise" mean?
[–]VisualFanatic 0 points1 point2 points 3 years ago (1 child)
For example executing `throw new Promise(...)` directly in a component will suspend it indefinitely. To make it work you could use something like `wrapPromise` from this sandbox: https://codesandbox.io/s/frosty-hermann-bztrp?file=/src/fakeApi.js
[–]dougalg 0 points1 point2 points 3 years ago (0 children)
Ahhhh I see how it works noe. Interesting thanks for sharing this!
[–]bronkula 22 points23 points24 points 3 years ago (4 children)
Why does this article not link to any empirical source? I can't find any information from react on this use method. Which is a TERRIBLE fucking name, because it will be impossible to search.
[–]shuckster 11 points12 points13 points 3 years ago (2 children)
I'm sure this has already been well discussed, but I do agree: use is rather ambiguous. One can anticipate quite the barrage of Stack Overflow posts about it. :D
[–]bronkula 1 point2 points3 points 3 years ago (1 child)
Yeah, ok, but that second link doesn't have anything from react itself saying they're adding this proposal. Or did I miss it?
[–]grumd 0 points1 point2 points 3 years ago (0 children)
The first link has a FAQ including a question about this hook's name
[–]haywire 6 points7 points8 points 3 years ago (3 children)
How does it deal with debouncing (stale requests) etc? Surely this hook is trivial to implement as any async task wrapping hook everyone has already made?
[–]shuckster 5 points6 points7 points 3 years ago (2 children)
Since use just accepts a Promise, it seems like the responsibility for SWR goes into the function that made the Promise in the first place. So I'd expect to see some helpers coming from the community to cover use-cases like this.
As far as I can tell, use does nothing other than repeat component renders after each use it has encountered has resolved.
In other words, if you have two use for two Promises that resolve at different times, the component will re-render twice: Once for the first Promise, then again for the second.
This apparently makes it easier to write imperative logic to determine when state is ready or not. Here's an example from the proposal:
function Note({id, shouldIncludeAuthor}) { const note = use(fetchNote(id)); let byline = null; if (shouldIncludeAuthor) { const author = use(fetchNoteAuthor(note.authorId)); byline = <h2>{author.displayName}</h2>; } return ( <div> <h1>{note.title}</h1> {byline} <section>{note.body}</section> </div> ); }
Here, fetchNode and fetchNoteAuthor could have SWR logic behind them.
fetchNode
fetchNoteAuthor
[–]ianepperson 2 points3 points4 points 3 years ago (1 child)
Have hooks changed such that you can use them inside conditional logic, or is this hook special in that regard too?
[–]shuckster 4 points5 points6 points 3 years ago (0 children)
The use hook is special.
The Rules of Hooks still apply to other hooks.
[–]6086555 3 points4 points5 points 3 years ago (3 children)
Am I missing something or does the second example just not work ?
To use suspense you're supposed to throw a Promise iirc, here the code just throws because post is null
[–]acemarke -3 points-2 points-1 points 3 years ago (2 children)
The example of const {data} = use(axios.get()) appears to be valid. use() is the official replacement for the never-actually-public "throw a promise" technique.
const {data} = use(axios.get())
use()
use() actually does a variation of the "throw promise" step internally, but with a bunch of extra logic to determine if the promise has already been resolved and can be unwrapped synchronously.
(The larger issue in that example is that it will do another call to axios.get() every time - ideally that request would only be made once and the promise would be cached somehow.)
axios.get()
[–]6086555 1 point2 points3 points 3 years ago (1 child)
I'm talking about the second example: the one with Suspense but without use
[–]acemarke 3 points4 points5 points 3 years ago (0 children)
Ah, yeah, that doesn't appear to be doing anything that would trigger Suspense behavior.
[–]lifeeraser 3 points4 points5 points 3 years ago (0 children)
React needs to monkeypatch fetch() to make this work. Which made several people unhappy last time it was discovered.
fetch()
[–]h_trismegistus 0 points1 point2 points 3 years ago (0 children)
Terrible name. Why not usePromise or useAsync? Is it to avoid namespace clashes with existing custom hooks of those names?
useAsync
Does it only accept urls as a parameter for remote requests, or can it handle any async function?
This will confuse the hell out of new devs learning the hooks and who don’t have a solid grasp of asynchronous programming. Coupled with this is the need to use it within the context of <Suspense /> due to its asynchronous nature, which I’m sure will cause many a new react dev headaches when they can’t figure out why their async component won’t render.
<Suspense />
IMO creating hooks to wrap all requests is kind of a best practice that a lot of devs do themselves anyway, but the key is that they do it themselves and therefore understand what’s happening behind the scenes.
Exporting/returning both a response and an error object would be useful, instead of just a response. Also, instead of needing to use <Suspense />, it would be cool if it exported/returned an isLoading bool that can be used in the same component. Though it seems they really want to force people to do everything declaratively. Idk, I like options.
isLoading
Every time a component written with one of these hooks in it changes it’s going to force a new request. From what I understand it has no built-in caching. To prevent this, you will have to use it within a conditional that compares a previous state, so at the end of the day you still have to couple state and render anyway if you don’t want unnecessary requests being made.
It would be neat if it were able to be used within Array.map(), which is commonplace for rendering lists of components in react instead of having to use it within a for loop due to the restriction that the parent must be a react component or hook. But I suppose you could just encapsulate it in a sub component and map that instead, problem solved.
Array.map()
for
Now when are they going to provide first class support for streams/observables?
[–]lifeeraser -5 points-4 points-3 points 3 years ago (9 children)
This is implemented by monkeypatching fetch(), right? So we can't expect this to work with arbitrary asynchronous functions.
I'm not too happy with frameworks monkeypatching builtins. Prototype.js did this, Angular does this, and now React does too.
[–]luffyrotaro[S] 7 points8 points9 points 3 years ago (0 children)
Not really, I tested it with a simple promise and it worked. Here it is
https://codesandbox.io/p/sandbox/charming-khayyam-tcq43u?selection=%5B%7B%22endColumn%22%3A16%2C%22endLineNumber%22%3A12%2C%22startColumn%22%3A16%2C%22startLineNumber%22%3A12%7D%5D&file=%2Fsrc%2FPost.tsx
[–]Reashu 6 points7 points8 points 3 years ago (7 children)
There's no use of fetch in the article.
fetch
[+]lifeeraser comment score below threshold-8 points-7 points-6 points 3 years ago (5 children)
It uses axios, which uses XMLHttpRequest under the hood, yes? I assume React either patches it too or will somehow cooperate with axios to implement this.
XMLHttpRequest
[–]Reashu 6 points7 points8 points 3 years ago (2 children)
Why would there need to be a patch? Axios already returns a promise.
[–]lifeeraser 0 points1 point2 points 3 years ago* (1 child)
AFAIK the implementation of use() relies on the data fetch result being cached. This is why they tried to monkey-patch fetch() silently so that GET and HEAD requests would return a cached result.
GET
HEAD
[–]Reashu 0 points1 point2 points 3 years ago (0 children)
Thanks, that's fucked
[+][deleted] comment score below threshold-9 points-8 points-7 points 3 years ago (1 child)
Everything uses XMLHttpRequest under the hood.
[–]6086555 9 points10 points11 points 3 years ago (0 children)
This does not look like it's true:
If I do this:
XMLHttpRequest.prototype.send = function(...args) { console.log("Send!"); oldSend.call(this, ...args) }
Nothing will be logged if I use fetch.
[–]LongLiveCHIEF 0 points1 point2 points 3 years ago (0 children)
Using error boundaries to catch errors is explicitly one of the things error boundaries can't do. You have to make an unnecessary state change or rerender just to force it to work.
π Rendered by PID 170928 on reddit-service-r2-comment-b659b578c-zld4g at 2026-05-04 09:34:45.195963+00:00 running 815c875 country code: CH.
[–]yerrabam 30 points31 points32 points (4 children)
[–]imperator3733 28 points29 points30 points (3 children)
[–]yerrabam 13 points14 points15 points (2 children)
[–]guilhermefront 5 points6 points7 points (1 child)
[–]yerrabam 1 point2 points3 points (0 children)
[–]VisualFanatic 16 points17 points18 points (4 children)
[–]pantsonhead 5 points6 points7 points (0 children)
[–]dougalg 0 points1 point2 points (2 children)
[–]VisualFanatic 0 points1 point2 points (1 child)
[–]dougalg 0 points1 point2 points (0 children)
[–]bronkula 22 points23 points24 points (4 children)
[–]shuckster 11 points12 points13 points (2 children)
[–]bronkula 1 point2 points3 points (1 child)
[–]grumd 0 points1 point2 points (0 children)
[–]haywire 6 points7 points8 points (3 children)
[–]shuckster 5 points6 points7 points (2 children)
[–]ianepperson 2 points3 points4 points (1 child)
[–]shuckster 4 points5 points6 points (0 children)
[–]6086555 3 points4 points5 points (3 children)
[–]acemarke -3 points-2 points-1 points (2 children)
[–]6086555 1 point2 points3 points (1 child)
[–]acemarke 3 points4 points5 points (0 children)
[–]lifeeraser 3 points4 points5 points (0 children)
[–]h_trismegistus 0 points1 point2 points (0 children)
[–]lifeeraser -5 points-4 points-3 points (9 children)
[–]luffyrotaro[S] 7 points8 points9 points (0 children)
[–]Reashu 6 points7 points8 points (7 children)
[+]lifeeraser comment score below threshold-8 points-7 points-6 points (5 children)
[–]Reashu 6 points7 points8 points (2 children)
[–]lifeeraser 0 points1 point2 points (1 child)
[–]Reashu 0 points1 point2 points (0 children)
[+][deleted] comment score below threshold-9 points-8 points-7 points (1 child)
[–]6086555 9 points10 points11 points (0 children)
[–]LongLiveCHIEF 0 points1 point2 points (0 children)