Open arackaf opened 2 years ago
I am experiencing this too.
From beta docs I remember use
is reserved for client only. So maybe you have to add 'use client' on top. However in my experience it doesn't work: it goes in infinite loop
@arackaf use()
is reserved for client components. You need to await
the promises and it should just work.
@pix303 probably because the awaited promise is not stable (referentially equal) between renders. A good explanation of what's happening can found in the RFC: https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#usepromise On @arackaf's example it should work fine since the promises are passed as props (unless the parent component re-renders the Promises will be stable).
Just checked in on this with @sebmarkbage. The component you currently have is an async function
server component that is using use()
, this is supposed to be a hooks lint warning which is on the list of things to implement. For async function
you have to use await
. If it's not an async server component use
works either should work:
// Async function server component
export const Todos: TodosType = async (props: Props) => {
const todos = await props.todos;
const colors = await props.colors;
return (
<section>
<TodoListFiltersHeader />
<ul>
{(todos?.data ?? []).map((todo, idx) => (
<li key={idx} style={{ color: colors.data[todo.color] }}>
{todo.name} - {todo.priority}
</li>
))}
</ul>
</section>
);
};
// Server Component
export const Todos: TodosType = (props: Props) => {
const todos = use(props.todos);
const colors = use(props.colors);
return (
<section>
<TodoListFiltersHeader />
<ul>
{(todos?.data ?? []).map((todo, idx) => (
<li key={idx} style={{ color: colors.data[todo.color] }}>
{todo.name} - {todo.priority}
</li>
))}
</ul>
</section>
);
};
@timneutkens thanks a ton! fwiw, my feedback would be that if it's not possible to get use
to be functional in a non-async RSC, I hope ya'll will consider making this a client-only feature; that's a pretty massive footgun.
Am I correct in assuming this breaks since, under the covers, use
works by throwing a promise, which, from an async function, gets turned into the return value from the async function, which is not what the calling RSC was expecting?
my feedback would be that if it's not possible to get use to be functional in a non-async RSC, I hope ya'll will consider making this a client-only feature; that's a pretty massive footgun.
To be clear: you can use use
in non-async components. You can't use it in async components. That's what the lint rule will enforce.
However there's no reason for it to crash with an out-of-memory exception. React should throw an error with a helpful message. We'll fix that.
Is it okay to leave this open so that we have something to track implementing the lint rule and can get back to you when it is implemented?
@timneutkens done! Was just trying to lessen your backlog by if just by a tiny amount :)
@acdlite sorry dumb typo on my part. I of course meant to say
my feedback would be that if it's not possible to get
use
to be functional in async RSCs, I hope ya'll will consider...
so wait - you said you're working on a fix for this? So, pending your fix, will use
be usable in all async RSCs? Or just some of them?
@acdlite ohhh - re-reading your comment for the third time, it looks like you want Promises to be valid React nodes, so my particular use of use
in an async component should not crash after your fix, but it also won't do what I want. Is that about right?
From beta docs I remember
use
is reserved for client only. So maybe you have to add 'use client' on top. However in my experience it doesn't work: it goes in infinite loop
I thought it was something with my setup at first and spent a lot of time debugging it. Have you found a way around this? Seems like the promise gets resolved, network inspector shows that the results come through and the fetch
call goes through, but the component just gets stuck in an infinite loop. Any guidance would be appreciated.
@KSubedi did you read the thread? use
cannot be used in an async RSC. It can only be used in a non-async RSC.
@KSubedi did you read the thread?
use
cannot be used in an async RSC. It can only be used in a non-async RSC.
I did read the thread. I apologize if it was not clear on my comment but I am having that infinite loop issue on a non-async client component just like @pix303 mentioned.
Hi @KSubedi regarding use()
in client components, you can read why you get infinite loops here: https://github.com/vercel/next.js/issues/42180#issuecomment-1303553483 and you can read this for the fix: https://github.com/vercel/next.js/issues/42180#issuecomment-1303676756
EDIT: also make sure you are on v13.0.2
or higher
@arackaf https://github.com/vercel/next.js/issues/42469#issuecomment-1303958773
ohhh - re-reading your comment for the third time, it looks like you want Promises to be valid React nodes, so my particular use of use in an async component should not crash after your fix, but it also won't do what I want. Is that about right?
Yeah. I think we'll still throw an error when we detect this (with a helpful message) but there's no reason it should cause an out-of-memory exception.
I'll update the original comment to clarify.
@acdlite thanks for clarifying!
Hi @KSubedi regarding
use()
in client components, you can read why you get infinite loops here: #42180 (comment) and you can read this for the fix: #42180 (comment)EDIT: also make sure you are on
v13.0.2
or higher
Thank you so much, wrapping it in cache
worked and its good to know why the behavior is like that.
Verify canary release
Provide environment information
---->npx --no-install next info
What browser are you using? (if relevant)
Chrome
How are you deploying your application? (if relevant)
n/a
Describe the Bug
I have a pretty rudimentary RSC demo coded up here:
https://github.com/arackaf/next-13-data-fetching-blog-post/blob/feature/use-bug-repro/app/Todos.tsx
When I unwrap the promise in the component using the data using
use
then Node freezes up. I see about 15+ Node tasks in activity monitor, with one of them at about 150%. Using await works fine.Eventually, after killing the Next watch, I get this
Expected Behavior
Use should work the same as await
Link to reproduction
https://github.com/arackaf/next-13-data-fetching-blog-post/blob/feature/use-bug-repro/app/Todos.tsx
To Reproduce
Clone that repo at that branch, and run. Swap the
use
calls out for the commented out await calls (after clearing the rogue Node processes) to see it work.