Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Component is not a function when using Suspense and forwardRef #26385

Closed
hansottowirtz opened this issue Mar 14, 2023 · 4 comments · Fixed by #26535
Closed

Bug: Component is not a function when using Suspense and forwardRef #26385

hansottowirtz opened this issue Mar 14, 2023 · 4 comments · Fixed by #26535

Comments

@hansottowirtz
Copy link
Contributor

hansottowirtz commented Mar 14, 2023

React version: 18.3.0-next-3ba7add60-20221201

Steps To Reproduce

I haven't been able to create a minimal example yet, if needed I will spend more time on it. However, it only seems to occur when Suspending components rerender in a specific order.

Description

The Component is not a function error is thrown when using Suspense and forwardRef together in a specific way.

It seems like react-reconciler doesn't properly handle forwardRefs in either renderWithHooksAgain, replaySuspendedComponentWithHooks, replayFunctionComponent or replaySuspendedUnitOfWork. The Component variable is not a function in this case, but a { $$typeof: Symbol(react.forward_ref), render: (props, ref) => any }. renderWithHooksAgain tries to execute Component(props, secondArg), which throws this error.

I'm not too familiar with React internals, if you can tell me how to trigger this codepath I can make a minimal reproduction more easily.

Screenshot 2023-03-14 at 14 55 13

@hansottowirtz hansottowirtz added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Mar 14, 2023
@hansottowirtz
Copy link
Contributor Author

hansottowirtz commented Mar 16, 2023

This patch solves it:

--- a/dist/compiled/react-dom/cjs/react-dom.development.js
+++ b/dist/compiled/react-dom/cjs/react-dom.development.js
@@ -30987,7 +30987,16 @@ function replaySuspendedUnitOfWork(unitOfWork) {
         var Component = unitOfWork.type;
         var unresolvedProps = unitOfWork.pendingProps;
         var resolvedProps = unitOfWork.elementType === Component ? unresolvedProps : resolveDefaultProps(Component, unresolvedProps);
-        next = replayFunctionComponent(current, unitOfWork, resolvedProps, Component, workInProgressRootRenderLanes);
+        var componentRender = null;
+        switch (unitOfWork.tag) {
+          case FunctionComponent:
+            componentRender = type;
+            break;
+          case ForwardRef:
+            componentRender = type.render;
+            break;
+        }
+        next = replayFunctionComponent(current, unitOfWork, resolvedProps, componentRender, workInProgressRootRenderLanes);
         break;
       }

A line like this exists in updateForwardRef, but doesn't seem to exist in the replay suspense logic.

const render = Component.render;

@hansottowirtz
Copy link
Contributor Author

@acdlite tagging you because I think the reconciler and suspense is your field of expertise. Happy to help with anything that can help solve this.

@acdlite
Copy link
Collaborator

acdlite commented Mar 17, 2023

Ah yeah that's a good find. Want to submit a PR with a regression test? :)

@hansottowirtz
Copy link
Contributor Author

Sure! Might need some help on how to trigger the replaySuspendedUnitOfWork function. I'll tag you in the PR.

hansottowirtz added a commit to hansottowirtz/react that referenced this issue Mar 17, 2023
hansottowirtz added a commit to hansottowirtz/react that referenced this issue Mar 29, 2023
@gaearon gaearon added Type: Bug and removed Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug labels Mar 29, 2023
hansottowirtz added a commit to hansottowirtz/react that referenced this issue Apr 1, 2023
hansottowirtz added a commit to hansottowirtz/react that referenced this issue Apr 2, 2023
acdlite added a commit that referenced this issue Apr 2, 2023
Continuation of #26420

Fixes #26385 and
#26419

---------

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>
github-actions bot pushed a commit that referenced this issue Apr 2, 2023
Continuation of #26420

Fixes #26385 and
#26419

---------

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>

DiffTrain build for [7329ea8](7329ea8)
jerrydev0927 added a commit to jerrydev0927/react that referenced this issue Jan 5, 2024
Continuation of facebook/react#26420

Fixes facebook/react#26385 and
facebook/react#26419

---------

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>

DiffTrain build for [7329ea81c154d40800e30104be40f050e8c2af3e](facebook/react@7329ea8)
EdisonVan pushed a commit to EdisonVan/react that referenced this issue Apr 15, 2024
Continuation of facebook#26420

Fixes facebook#26385 and
facebook#26419

---------

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants