@samitouri / QOS-React / commits / 9d76c954cf

[Flight] Error if a legacy React Element is attempted to be rendered (#29043)

This errors on the client normally but in the case the `type` is a function - i.e. a Server Component - it wouldn't be transferred to error on the client so you end up with a worse error message. So this just implements the same check as ChildFiber.

Sebastian Markbåge committed May 10, 2024 at 09:37 UTC 9d76c954cfe134d7f541c3e706e344e6845ba235
2 files changed +38
packages/react-client/src/__tests__/ReactFlight-test.js
+28
@@ -938,6 +938,7 @@ describe('ReactFlight', () => {
938 });
939 });
940
941 + // @gate renameElementSymbol
942 it('should emit descriptions of errors in dev', async () => {
943 const ClientErrorBoundary = clientReference(ErrorBoundary);
944
@@ -945,6 +946,21 @@ describe('ReactFlight', () => {
946 throw value;
947 }
948
949 + function RenderInlined() {
950 + const inlinedElement = {
951 + $$typeof: Symbol.for('react.element'),
952 + type: () => {},
953 + key: null,
954 + ref: null,
955 + props: {},
956 + _owner: null,
957 + };
958 + return inlinedElement;
959 + }
960 +
961 + // We wrap in lazy to ensure the errors throws lazily.
962 + const LazyInlined = React.lazy(async () => ({default: RenderInlined}));
963 +
964 const testCases = (
965 <>
966 <ClientErrorBoundary expectedMessage="This is a real Error.">
@@ -1010,6 +1026,18 @@ describe('ReactFlight', () => {
1026 <Throw value={['array']} />
1027 </div>
1028 </ClientErrorBoundary>
1029 + <ClientErrorBoundary
1030 + expectedMessage={
1031 + 'A React Element from an older version of React was rendered. ' +
1032 + 'This is not supported. It can happen if:\n' +
1033 + '- Multiple copies of the "react" package is used.\n' +
1034 + '- A library pre-bundled an old copy of "react" or "react/jsx-runtime".\n' +
1035 + '- A compiler tries to "inline" JSX instead of using the runtime.'
1036 + }>
1037 + <div>
1038 + <LazyInlined />
1039 + </div>
1040 + </ClientErrorBoundary>
1041 </>
1042 );
1043
packages/react-server/src/ReactFlightServer.js
+10
@@ -99,6 +99,7 @@ import {resolveOwner, setCurrentOwner} from './flight/ReactFlightCurrentOwner';
99 import {
100 getIteratorFn,
101 REACT_ELEMENT_TYPE,
102 + REACT_LEGACY_ELEMENT_TYPE,
103 REACT_FORWARD_REF_TYPE,
104 REACT_FRAGMENT_TYPE,
105 REACT_LAZY_TYPE,
@@ -2004,6 +2005,15 @@ function renderModelDestructive(
2005 resolvedModel,
2006 );
2007 }
2008 + case REACT_LEGACY_ELEMENT_TYPE: {
2009 + throw new Error(
2010 + 'A React Element from an older version of React was rendered. ' +
2011 + 'This is not supported. It can happen if:\n' +
2012 + '- Multiple copies of the "react" package is used.\n' +
2013 + '- A library pre-bundled an old copy of "react" or "react/jsx-runtime".\n' +
2014 + '- A compiler tries to "inline" JSX instead of using the runtime.',
2015 + );
2016 + }
2017 }
2018
2019 if (isClientReference(value)) {