@samitouri / QOS-React-2 / commits / 75f3ddebfa

Remove experimental useOpaqueIdentifier API (#22672)

useId is the updated version of this API.

Andrew Clark committed Nov 1, 2021 at 18:02 UTC 75f3ddebfa0d9885ce8df42571cf0c09ad6c0a3b
39 files changed +22 -1790
packages/react-art/src/ReactARTHostConfig.js
-18
@@ -436,24 +436,6 @@ export function getInstanceFromNode(node) {
436 throw new Error('Not implemented.');
437 }
438
439 -export function isOpaqueHydratingObject(value: mixed): boolean {
440 - throw new Error('Not implemented.');
441 -}
442 -
443 -export function makeOpaqueHydratingObject(
444 - attemptToReadValue: () => void,
445 -): OpaqueIDType {
446 - throw new Error('Not implemented.');
447 -}
448 -
449 -export function makeClientId(): OpaqueIDType {
450 - throw new Error('Not implemented.');
451 -}
452 -
453 -export function makeClientIdInDEV(warnOnAccessInDEV: () => void): OpaqueIDType {
454 - throw new Error('Not implemented.');
455 -}
456 -
439 export function beforeActiveInstanceBlur(internalInstanceHandle: Object) {
440 // noop
441 }
packages/react-debug-tools/src/ReactDebugHooks.js
-26
@@ -18,13 +18,9 @@ import type {
18 Fiber,
19 Dispatcher as DispatcherType,
20 } from 'react-reconciler/src/ReactInternalTypes';
21 -import type {OpaqueIDType} from 'react-reconciler/src/ReactFiberHostConfig';
22 -
23 -import {NoMode} from 'react-reconciler/src/ReactTypeOfMode';
21
22 import ErrorStackParser from 'error-stack-parser';
23 import ReactSharedInternals from 'shared/ReactSharedInternals';
27 -import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
24 import {
25 FunctionComponent,
26 SimpleMemoComponent,
@@ -53,8 +49,6 @@ type Dispatch<A> = A => void;
49
50 let primitiveStackCache: null | Map<string, Array<any>> = null;
51
56 -let currentFiber: Fiber | null = null;
57 -
52 type Hook = {
53 memoizedState: any,
54 next: Hook | null,
@@ -324,23 +318,6 @@ function useDeferredValue<T>(value: T): T {
318 return value;
319 }
320
327 -function useOpaqueIdentifier(): OpaqueIDType | void {
328 - const hook = nextHook(); // State
329 - if (currentFiber && currentFiber.mode === NoMode) {
330 - nextHook(); // Effect
331 - }
332 - let value = hook === null ? undefined : hook.memoizedState;
333 - if (value && value.$$typeof === REACT_OPAQUE_ID_TYPE) {
334 - value = undefined;
335 - }
336 - hookLog.push({
337 - primitive: 'OpaqueIdentifier',
338 - stackError: new Error(),
339 - value,
340 - });
341 - return value;
342 -}
343 -
321 function useId(): string {
322 const hook = nextHook();
323 const id = hook !== null ? hook.memoizedState : '';
@@ -371,7 +348,6 @@ const Dispatcher: DispatcherType = {
348 useMutableSource,
349 useSyncExternalStore,
350 useDeferredValue,
374 - useOpaqueIdentifier,
351 useId,
352 };
353
@@ -767,8 +743,6 @@ export function inspectHooksOfFiber(
743 currentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
744 }
745
770 - currentFiber = fiber;
771 -
746 if (
747 fiber.tag !== FunctionComponent &&
748 fiber.tag !== SimpleMemoComponent &&
packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js
-58
@@ -598,64 +598,6 @@ describe('ReactHooksInspectionIntegration', () => {
598 ]);
599 });
600
601 - it('should support composite useOpaqueIdentifier hook', () => {
602 - function Foo(props) {
603 - const id = React.unstable_useOpaqueIdentifier();
604 - const [state] = React.useState(() => 'hello', []);
605 - return <div id={id}>{state}</div>;
606 - }
607 -
608 - const renderer = ReactTestRenderer.create(<Foo />);
609 - const childFiber = renderer.root.findByType(Foo)._currentFiber();
610 - const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
611 -
612 - expect(tree.length).toEqual(2);
613 -
614 - expect(tree[0].id).toEqual(0);
615 - expect(tree[0].isStateEditable).toEqual(false);
616 - expect(tree[0].name).toEqual('OpaqueIdentifier');
617 - expect(String(tree[0].value).startsWith('c_')).toBe(true);
618 -
619 - expect(tree[1]).toEqual({
620 - id: 1,
621 - isStateEditable: true,
622 - name: 'State',
623 - value: 'hello',
624 - subHooks: [],
625 - });
626 - });
627 -
628 - it('should support composite useOpaqueIdentifier hook in concurrent mode', () => {
629 - function Foo(props) {
630 - const id = React.unstable_useOpaqueIdentifier();
631 - const [state] = React.useState('hello');
632 - return <div id={id}>{state}</div>;
633 - }
634 -
635 - const renderer = ReactTestRenderer.create(<Foo />, {
636 - unstable_isConcurrent: true,
637 - });
638 - expect(Scheduler).toFlushWithoutYielding();
639 -
640 - const childFiber = renderer.root.findByType(Foo)._currentFiber();
641 - const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
642 -
643 - expect(tree.length).toEqual(2);
644 -
645 - expect(tree[0].id).toEqual(0);
646 - expect(tree[0].isStateEditable).toEqual(false);
647 - expect(tree[0].name).toEqual('OpaqueIdentifier');
648 - expect(String(tree[0].value).startsWith('c_')).toBe(true);
649 -
650 - expect(tree[1]).toEqual({
651 - id: 1,
652 - isStateEditable: true,
653 - name: 'State',
654 - value: 'hello',
655 - subHooks: [],
656 - });
657 - });
658 -
601 it('should support useId hook', () => {
602 function Foo(props) {
603 const id = React.unstable_useId();
packages/react-devtools-shared/src/backend/ReactSymbols.js
-3
@@ -40,9 +40,6 @@ export const LAZY_SYMBOL_STRING = 'Symbol(react.lazy)';
40 export const MEMO_NUMBER = 0xead3;
41 export const MEMO_SYMBOL_STRING = 'Symbol(react.memo)';
42
43 -export const OPAQUE_ID_NUMBER = 0xeae0;
44 -export const OPAQUE_ID_SYMBOL_STRING = 'Symbol(react.opaque.id)';
45 -
43 export const PORTAL_NUMBER = 0xeaca;
44 export const PORTAL_SYMBOL_STRING = 'Symbol(react.portal)';
45
packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js
-1109
@@ -17,8 +17,6 @@ let React;
17 let ReactDOM;
18 let ReactDOMServer;
19 let ReactTestUtils;
20 -let act;
21 -let Scheduler;
20 let useState;
21 let useReducer;
22 let useEffect;
@@ -30,7 +28,6 @@ let useImperativeHandle;
28 let useInsertionEffect;
29 let useLayoutEffect;
30 let useDebugValue;
33 -let useOpaqueIdentifier;
31 let forwardRef;
32 let yieldedValues;
33 let yieldValue;
@@ -44,8 +41,6 @@ function initModules() {
41 ReactDOM = require('react-dom');
42 ReactDOMServer = require('react-dom/server');
43 ReactTestUtils = require('react-dom/test-utils');
47 - Scheduler = require('scheduler');
48 - act = require('jest-react').act;
44 useState = React.useState;
45 useReducer = React.useReducer;
46 useEffect = React.useEffect;
@@ -57,7 +52,6 @@ function initModules() {
52 useImperativeHandle = React.useImperativeHandle;
53 useInsertionEffect = React.useInsertionEffect;
54 useLayoutEffect = React.useLayoutEffect;
60 - useOpaqueIdentifier = React.unstable_useOpaqueIdentifier;
55 forwardRef = React.forwardRef;
56
57 yieldedValues = [];
@@ -83,9 +77,6 @@ const {
77 itRenders,
78 itThrowsWhenRendering,
79 serverRender,
86 - streamRender,
87 - clientCleanRender,
88 - clientRenderOnServerString,
80 } = ReactDOMServerIntegrationUtils(initModules);
81
82 describe('ReactDOMServerHooks', () => {
@@ -910,1104 +901,4 @@ describe('ReactDOMServerHooks', () => {
901 );
902 expect(container.children[0].textContent).toEqual('0');
903 });
913 -
914 - describe('useOpaqueIdentifier', () => {
915 - it('generates unique ids for server string render', async () => {
916 - function App(props) {
917 - const idOne = useOpaqueIdentifier();
918 - const idTwo = useOpaqueIdentifier();
919 - return (
920 - <div>
921 - <div aria-labelledby={idOne} />
922 - <div id={idOne} />
923 - <span aria-labelledby={idTwo} />
924 - <span id={idTwo} />
925 - </div>
926 - );
927 - }
928 -
929 - const domNode = await serverRender(<App />);
930 - expect(domNode.children.length).toEqual(4);
931 - expect(domNode.children[0].getAttribute('aria-labelledby')).toEqual(
932 - domNode.children[1].getAttribute('id'),
933 - );
934 - expect(domNode.children[2].getAttribute('aria-labelledby')).toEqual(
935 - domNode.children[3].getAttribute('id'),
936 - );
937 - expect(domNode.children[0].getAttribute('aria-labelledby')).not.toEqual(
938 - domNode.children[2].getAttribute('aria-labelledby'),
939 - );
940 - expect(
941 - domNode.children[0].getAttribute('aria-labelledby'),
942 - ).not.toBeNull();
943 - expect(
944 - domNode.children[2].getAttribute('aria-labelledby'),
945 - ).not.toBeNull();
946 - });
947 -
948 - it('generates unique ids for server stream render', async () => {
949 - function App(props) {
950 - const idOne = useOpaqueIdentifier();
951 - const idTwo = useOpaqueIdentifier();
952 - return (
953 - <div>
954 - <div aria-labelledby={idOne} />
955 - <div id={idOne} />
956 - <span aria-labelledby={idTwo} />
957 - <span id={idTwo} />
958 - </div>
959 - );
960 - }
961 -
962 - const domNode = await streamRender(<App />);
963 - expect(domNode.children.length).toEqual(4);
964 - expect(domNode.children[0].getAttribute('aria-labelledby')).toEqual(
965 - domNode.children[1].getAttribute('id'),
966 - );
967 - expect(domNode.children[2].getAttribute('aria-labelledby')).toEqual(
968 - domNode.children[3].getAttribute('id'),
969 - );
970 - expect(domNode.children[0].getAttribute('aria-labelledby')).not.toEqual(
971 - domNode.children[2].getAttribute('aria-labelledby'),
972 - );
973 - expect(
974 - domNode.children[0].getAttribute('aria-labelledby'),
975 - ).not.toBeNull();
976 - expect(
977 - domNode.children[2].getAttribute('aria-labelledby'),
978 - ).not.toBeNull();
979 - });
980 -
981 - it('generates unique ids for client render', async () => {
982 - function App(props) {
983 - const idOne = useOpaqueIdentifier();
984 - const idTwo = useOpaqueIdentifier();
985 - return (
986 - <div>
987 - <div aria-labelledby={idOne} />
988 - <div id={idOne} />
989 - <span aria-labelledby={idTwo} />
990 - <span id={idTwo} />
991 - </div>
992 - );
993 - }
994 -
995 - const domNode = await clientCleanRender(<App />);
996 - expect(domNode.children.length).toEqual(4);
997 - expect(domNode.children[0].getAttribute('aria-labelledby')).toEqual(
998 - domNode.children[1].getAttribute('id'),
999 - );
1000 - expect(domNode.children[2].getAttribute('aria-labelledby')).toEqual(
1001 - domNode.children[3].getAttribute('id'),
1002 - );
1003 - expect(domNode.children[0].getAttribute('aria-labelledby')).not.toEqual(
1004 - domNode.children[2].getAttribute('aria-labelledby'),
1005 - );
1006 - expect(
1007 - domNode.children[0].getAttribute('aria-labelledby'),
1008 - ).not.toBeNull();
1009 - expect(
1010 - domNode.children[2].getAttribute('aria-labelledby'),
1011 - ).not.toBeNull();
1012 - });
1013 -
1014 - it('generates unique ids for client render on good server markup', async () => {
1015 - function App(props) {
1016 - const idOne = useOpaqueIdentifier();
1017 - const idTwo = useOpaqueIdentifier();
1018 - return (
1019 - <div>
1020 - <div aria-labelledby={idOne} />
1021 - <div id={idOne} />
1022 - <span aria-labelledby={idTwo} />
1023 - <span id={idTwo} />
1024 - </div>
1025 - );
1026 - }
1027 -
1028 - const domNode = await clientRenderOnServerString(<App />);
1029 - expect(domNode.children.length).toEqual(4);
1030 - expect(domNode.children[0].getAttribute('aria-labelledby')).toEqual(
1031 - domNode.children[1].getAttribute('id'),
1032 - );
1033 - expect(domNode.children[2].getAttribute('aria-labelledby')).toEqual(
1034 - domNode.children[3].getAttribute('id'),
1035 - );
1036 - expect(domNode.children[0].getAttribute('aria-labelledby')).not.toEqual(
1037 - domNode.children[2].getAttribute('aria-labelledby'),
1038 - );
1039 - expect(
1040 - domNode.children[0].getAttribute('aria-labelledby'),
1041 - ).not.toBeNull();
1042 - expect(
1043 - domNode.children[2].getAttribute('aria-labelledby'),
1044 - ).not.toBeNull();
1045 - });
1046 -
1047 - it('useOpaqueIdentifier does not change id even if the component updates during client render', async () => {
1048 - let _setShowId;
1049 - function App() {
1050 - const id = useOpaqueIdentifier();
1051 - const [showId, setShowId] = useState(false);
1052 - _setShowId = setShowId;
1053 - return (
1054 - <div>
1055 - <div aria-labelledby={id} />
1056 - {showId && <div id={id} />}
1057 - </div>
1058 - );
1059 - }
1060 -
1061 - const domNode = await clientCleanRender(<App />);
1062 - const oldClientId = domNode.children[0].getAttribute('aria-labelledby');
1063 -
1064 - expect(domNode.children.length).toEqual(1);
1065 - expect(oldClientId).not.toBeNull();
1066 -
1067 - await act(async () => _setShowId(true));
1068 -
1069 - expect(domNode.children.length).toEqual(2);
1070 - expect(domNode.children[0].getAttribute('aria-labelledby')).toEqual(
1071 - domNode.children[1].getAttribute('id'),
1072 - );
1073 - expect(domNode.children[0].getAttribute('aria-labelledby')).toEqual(
1074 - oldClientId,
1075 - );
1076 - });
1077 -
1078 - it('useOpaqueIdentifier identifierPrefix works for server renderer and does not clash', async () => {
1079 - function ChildTwo({id}) {
1080 - return <div id={id}>Child Three</div>;
1081 - }
1082 - function App() {
1083 - const id = useOpaqueIdentifier();
1084 - const idTwo = useOpaqueIdentifier();
1085 -
1086 - return (
1087 - <div>
1088 - <div aria-labelledby={id}>Child One</div>
1089 - <ChildTwo id={id} />
1090 - <div aria-labelledby={idTwo}>Child Three</div>
1091 - <div id={idTwo}>Child Four</div>
1092 - </div>
1093 - );
1094 - }
1095 -
1096 - const containerOne = document.createElement('div');
1097 - document.body.append(containerOne);
1098 -
1099 - containerOne.innerHTML = ReactDOMServer.renderToString(<App />, {
1100 - identifierPrefix: 'one',
1101 - });
1102 -
1103 - const containerTwo = document.createElement('div');
1104 - document.body.append(containerTwo);
1105 -
1106 - containerTwo.innerHTML = ReactDOMServer.renderToString(<App />, {
1107 - identifierPrefix: 'two',
1108 - });
1109 -
1110 - expect(document.body.children.length).toEqual(2);
1111 - const childOne = document.body.children[0];
1112 - const childTwo = document.body.children[1];
1113 -
1114 - expect(
1115 - childOne.children[0].children[0].getAttribute('aria-labelledby'),
1116 - ).toEqual(childOne.children[0].children[1].getAttribute('id'));
1117 - expect(
1118 - childOne.children[0].children[2].getAttribute('aria-labelledby'),
1119 - ).toEqual(childOne.children[0].children[3].getAttribute('id'));
1120 -
1121 - expect(
1122 - childOne.children[0].children[0].getAttribute('aria-labelledby'),
1123 - ).not.toEqual(
1124 - childOne.children[0].children[2].getAttribute('aria-labelledby'),
1125 - );
1126 -
1127 - expect(
1128 - childOne.children[0].children[0]
1129 - .getAttribute('aria-labelledby')
1130 - .startsWith('one'),
1131 - ).toBe(true);
1132 - expect(
1133 - childOne.children[0].children[2]
1134 - .getAttribute('aria-labelledby')
1135 - .includes('one'),
1136 - ).toBe(true);
1137 -
1138 - expect(
1139 - childTwo.children[0].children[0].getAttribute('aria-labelledby'),
1140 - ).toEqual(childTwo.children[0].children[1].getAttribute('id'));
1141 - expect(
1142 - childTwo.children[0].children[2].getAttribute('aria-labelledby'),
1143 - ).toEqual(childTwo.children[0].children[3].getAttribute('id'));
1144 -
1145 - expect(
1146 - childTwo.children[0].children[0].getAttribute('aria-labelledby'),
1147 - ).not.toEqual(
1148 - childTwo.children[0].children[2].getAttribute('aria-labelledby'),
1149 - );
1150 -
1151 - expect(
1152 - childTwo.children[0].children[0]
1153 - .getAttribute('aria-labelledby')
1154 - .startsWith('two'),
1155 - ).toBe(true);
1156 - expect(
1157 - childTwo.children[0].children[2]
1158 - .getAttribute('aria-labelledby')
1159 - .startsWith('two'),
1160 - ).toBe(true);
1161 - });
1162 -
1163 - it('useOpaqueIdentifier identifierPrefix works for multiple reads on a streaming server renderer', async () => {
1164 - function ChildTwo() {
1165 - const id = useOpaqueIdentifier();
1166 -
1167 - return <div id={id}>Child Two</div>;
1168 - }
1169 -
1170 - function App() {
1171 - const id = useOpaqueIdentifier();
1172 -
1173 - return (
1174 - <>
1175 - <div id={id}>Child One</div>
1176 - <ChildTwo />
1177 - <div aria-labelledby={id}>Aria One</div>
1178 - </>
1179 - );
1180 - }
1181 -
1182 - const container = document.createElement('div');
1183 - document.body.append(container);
1184 -
1185 - const streamOne = ReactDOMServer.renderToNodeStream(<App />, {
1186 - identifierPrefix: 'one',
1187 - }).setEncoding('utf8');
1188 - const streamTwo = ReactDOMServer.renderToNodeStream(<App />, {
1189 - identifierPrefix: 'two',
1190 - }).setEncoding('utf8');
1191 -
1192 - const streamOneIsDone = new Promise((resolve, reject) => {
1193 - streamOne.on('end', () => resolve());
1194 - streamOne.on('error', e => reject(e));
1195 - });
1196 - const streamTwoIsDone = new Promise((resolve, reject) => {
1197 - streamTwo.on('end', () => resolve());
1198 - streamTwo.on('error', e => reject(e));
1199 - });
1200 -
1201 - const containerOne = document.createElement('div');
1202 - const containerTwo = document.createElement('div');
1203 -
1204 - streamOne._read(10);
1205 - streamTwo._read(10);
1206 -
1207 - containerOne.innerHTML = streamOne.read();
1208 - containerTwo.innerHTML = streamTwo.read();
1209 -
1210 - expect(containerOne.children[0].getAttribute('id')).not.toEqual(
1211 - containerOne.children[1].getAttribute('id'),
1212 - );
1213 - expect(containerTwo.children[0].getAttribute('id')).not.toEqual(
1214 - containerTwo.children[1].getAttribute('id'),
1215 - );
1216 - expect(containerOne.children[0].getAttribute('id')).not.toEqual(
1217 - containerTwo.children[0].getAttribute('id'),
1218 - );
1219 - expect(containerOne.children[0].getAttribute('id').includes('one')).toBe(
1220 - true,
1221 - );
1222 - expect(containerOne.children[1].getAttribute('id').includes('one')).toBe(
1223 - true,
1224 - );
1225 - expect(containerTwo.children[0].getAttribute('id').includes('two')).toBe(
1226 - true,
1227 - );
1228 - expect(containerTwo.children[1].getAttribute('id').includes('two')).toBe(
1229 - true,
1230 - );
1231 -
1232 - expect(containerOne.children[1].getAttribute('id')).not.toEqual(
1233 - containerTwo.children[1].getAttribute('id'),
1234 - );
1235 - expect(containerOne.children[0].getAttribute('id')).toEqual(
1236 - containerOne.children[2].getAttribute('aria-labelledby'),
1237 - );
1238 - expect(containerTwo.children[0].getAttribute('id')).toEqual(
1239 - containerTwo.children[2].getAttribute('aria-labelledby'),
1240 - );
1241 -
1242 - // Exhaust the rest of the stream
1243 - class Sink extends require('stream').Writable {
1244 - _write(chunk, encoding, done) {
1245 - done();
1246 - }
1247 - }
1248 - streamOne.pipe(new Sink());
1249 - streamTwo.pipe(new Sink());
1250 -
1251 - await Promise.all([streamOneIsDone, streamTwoIsDone]);
1252 - });
1253 -
1254 - it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered', async () => {
1255 - let _setShowDiv;
1256 - function App() {
1257 - const id = useOpaqueIdentifier();
1258 - const [showDiv, setShowDiv] = useState(false);
1259 - _setShowDiv = setShowDiv;
1260 -
1261 - return (
1262 - <div>
1263 - <div id={id}>Child One</div>
1264 - {showDiv && <div id={id}>Child Two</div>}
1265 - </div>
1266 - );
1267 - }
1268 -
1269 - const container = document.createElement('div');
1270 - document.body.append(container);
1271 -
1272 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1273 - const root = ReactDOM.createRoot(container, {hydrate: true});
1274 - root.render(<App />);
1275 - Scheduler.unstable_flushAll();
1276 - jest.runAllTimers();
1277 -
1278 - expect(container.children[0].children.length).toEqual(1);
1279 - const oldServerId = container.children[0].children[0].getAttribute('id');
1280 - expect(oldServerId).not.toBeNull();
1281 -
1282 - await act(async () => {
1283 - _setShowDiv(true);
1284 - });
1285 - expect(container.children[0].children.length).toEqual(2);
1286 - expect(container.children[0].children[0].getAttribute('id')).toEqual(
1287 - container.children[0].children[1].getAttribute('id'),
1288 - );
1289 - expect(container.children[0].children[0].getAttribute('id')).not.toEqual(
1290 - oldServerId,
1291 - );
1292 - expect(
1293 - container.children[0].children[0].getAttribute('id'),
1294 - ).not.toBeNull();
1295 - });
1296 -
1297 - it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered for legacy', async () => {
1298 - let _setShowDiv;
1299 - function App() {
1300 - const id = useOpaqueIdentifier();
1301 - const [showDiv, setShowDiv] = useState(false);
1302 - _setShowDiv = setShowDiv;
1303 -
1304 - return (
1305 - <div>
1306 - <div id={id}>Child One</div>
1307 - {showDiv && <div id={id}>Child Two</div>}
1308 - </div>
1309 - );
1310 - }
1311 -
1312 - const container = document.createElement('div');
1313 - document.body.append(container);
1314 -
1315 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1316 - ReactDOM.hydrate(<App />, container);
1317 -
1318 - expect(container.children[0].children.length).toEqual(1);
1319 - const oldServerId = container.children[0].children[0].getAttribute('id');
1320 - expect(oldServerId).not.toBeNull();
1321 -
1322 - await act(async () => {
1323 - _setShowDiv(true);
1324 - });
1325 - expect(container.children[0].children.length).toEqual(2);
1326 - expect(container.children[0].children[0].getAttribute('id')).toEqual(
1327 - container.children[0].children[1].getAttribute('id'),
1328 - );
1329 - expect(container.children[0].children[0].getAttribute('id')).not.toEqual(
1330 - oldServerId,
1331 - );
1332 - expect(
1333 - container.children[0].children[0].getAttribute('id'),
1334 - ).not.toBeNull();
1335 - });
1336 -
1337 - it('useOpaqueIdentifier: ID is not used during hydration but is used in an update', async () => {
1338 - let _setShow;
1339 - function App({unused}) {
1340 - Scheduler.unstable_yieldValue('App');
1341 - const id = useOpaqueIdentifier();
1342 - const [show, setShow] = useState(false);
1343 - _setShow = setShow;
1344 - return (
1345 - <div>
1346 - <span id={show ? id : null}>{'Child One'}</span>
1347 - </div>
1348 - );
1349 - }
1350 -
1351 - const container = document.createElement('div');
1352 - document.body.append(container);
1353 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1354 - const root = ReactDOM.createRoot(container, {hydrate: true});
1355 - act(() => {
1356 - root.render(<App />);
1357 - });
1358 - expect(Scheduler).toHaveYielded(['App', 'App']);
1359 - // The ID goes from not being used to being added to the page
1360 - act(() => {
1361 - _setShow(true);
1362 - });
1363 - expect(Scheduler).toHaveYielded(['App', 'App']);
1364 - expect(
1365 - container.getElementsByTagName('span')[0].getAttribute('id'),
1366 - ).not.toBeNull();
1367 - });
1368 -
1369 - it('useOpaqueIdentifier: ID is not used during hydration but is used in an update in legacy', async () => {
1370 - let _setShow;
1371 - function App({unused}) {
1372 - Scheduler.unstable_yieldValue('App');
1373 - const id = useOpaqueIdentifier();
1374 - const [show, setShow] = useState(false);
1375 - _setShow = setShow;
1376 - return (
1377 - <div>
1378 - <span id={show ? id : null}>{'Child One'}</span>
1379 - </div>
1380 - );
1381 - }
1382 -
1383 - const container = document.createElement('div');
1384 - document.body.append(container);
1385 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1386 - ReactDOM.hydrate(<App />, container);
1387 - expect(Scheduler).toHaveYielded(['App', 'App']);
1388 - // The ID goes from not being used to being added to the page
1389 - act(() => {
1390 - _setShow(true);
1391 - });
1392 - expect(Scheduler).toHaveYielded(['App']);
1393 - expect(
1394 - container.getElementsByTagName('span')[0].getAttribute('id'),
1395 - ).not.toBeNull();
1396 - });
1397 -
1398 - it('useOpaqueIdentifier: flushSync', async () => {
1399 - let _setShow;
1400 - function App() {
1401 - const id = useOpaqueIdentifier();
1402 - const [show, setShow] = useState(false);
1403 - _setShow = setShow;
1404 - return (
1405 - <div>
1406 - <span id={show ? id : null}>{'Child One'}</span>
1407 - </div>
1408 - );
1409 - }
1410 -
1411 - const container = document.createElement('div');
1412 - document.body.append(container);
1413 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1414 - const root = ReactDOM.createRoot(container, {hydrate: true});
1415 - act(() => {
1416 - root.render(<App />);
1417 - });
1418 -
1419 - // The ID goes from not being used to being added to the page
1420 - act(() => {
1421 - ReactDOM.flushSync(() => {
1422 - _setShow(true);
1423 - });
1424 - });
1425 - expect(
1426 - container.getElementsByTagName('span')[0].getAttribute('id'),
1427 - ).not.toBeNull();
1428 - });
1429 -
1430 - it('useOpaqueIdentifier: children with id hydrates before other children if ID updates', async () => {
1431 - let _setShow;
1432 -
1433 - const child1Ref = React.createRef();
1434 - const childWithIDRef = React.createRef();
1435 - const setShowRef = React.createRef();
1436 -
1437 - // RENAME THESE
1438 - function Child1() {
1439 - Scheduler.unstable_yieldValue('Child One');
1440 - return <span ref={child1Ref}>{'Child One'}</span>;
1441 - }
1442 -
1443 - function Child2() {
1444 - Scheduler.unstable_yieldValue('Child Two');
1445 - return <span>{'Child Two'}</span>;
1446 - }
1447 -
1448 - const Children = React.memo(function Children() {
1449 - return (
1450 - <React.Suspense fallback="Loading 1...">
1451 - <Child1 />
1452 - <Child2 />
1453 - </React.Suspense>
1454 - );
1455 - });
1456 -
1457 - function ChildWithID({parentID}) {
1458 - Scheduler.unstable_yieldValue('Child with ID');
1459 - return (
1460 - <span id={parentID} ref={childWithIDRef}>
1461 - {'Child with ID'}
1462 - </span>
1463 - );
1464 - }
1465 -
1466 - const ChildrenWithID = React.memo(function ChildrenWithID({parentID}) {
1467 - return (
1468 - <React.Suspense fallback="Loading 2...">
1469 - <ChildWithID parentID={parentID} />
1470 - </React.Suspense>
1471 - );
1472 - });
1473 -
1474 - function App() {
1475 - const id = useOpaqueIdentifier();
1476 - const [show, setShow] = useState(false);
1477 - _setShow = setShow;
1478 - return (
1479 - <div>
1480 - <Children />
1481 - <ChildrenWithID parentID={id} />
1482 - {show && (
1483 - <span aria-labelledby={id} ref={setShowRef}>
1484 - {'Child Three'}
1485 - </span>
1486 - )}
1487 - </div>
1488 - );
1489 - }
1490 -
1491 - const container = document.createElement('div');
1492 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1493 - expect(Scheduler).toHaveYielded([
1494 - 'Child One',
1495 - 'Child Two',
1496 - 'Child with ID',
1497 - ]);
1498 - expect(container.textContent).toEqual('Child OneChild TwoChild with ID');
1499 -
1500 - const serverId = container
1501 - .getElementsByTagName('span')[2]
1502 - .getAttribute('id');
1503 - expect(serverId).not.toBeNull();
1504 -
1505 - const root = ReactDOM.createRoot(container, {hydrate: true});
1506 - root.render(<App show={false} />);
1507 - expect(Scheduler).toHaveYielded([]);
1508 -
1509 - //Hydrate just child one before updating state
1510 - expect(Scheduler).toFlushAndYieldThrough(['Child One']);
1511 - expect(child1Ref.current).toBe(null);
1512 - expect(Scheduler).toHaveYielded([]);
1513 -
1514 - act(() => {
1515 - _setShow(true);
1516 -
1517 - // State update should trigger the ID to update, which changes the props
1518 - // of ChildWithID. This should cause ChildWithID to hydrate before Children
1519 -
1520 - expect(Scheduler).toFlushAndYieldThrough([
1521 - 'Child with ID',
1522 - // Fallbacks are immediately committed in TestUtils version
1523 - // of act
1524 - // 'Child with ID',
1525 - // 'Child with ID',
1526 - 'Child One',
1527 - 'Child Two',
1528 - ]);
1529 -
1530 - expect(child1Ref.current).toBe(null);
1531 - expect(childWithIDRef.current).toEqual(
1532 - container.getElementsByTagName('span')[2],
1533 - );
1534 -
1535 - expect(setShowRef.current).toEqual(
1536 - container.getElementsByTagName('span')[3],
1537 - );
1538 -
1539 - expect(childWithIDRef.current.getAttribute('id')).toEqual(
1540 - setShowRef.current.getAttribute('aria-labelledby'),
1541 - );
1542 - expect(childWithIDRef.current.getAttribute('id')).not.toEqual(serverId);
1543 - });
1544 -
1545 - // Children hydrates after ChildWithID
1546 - expect(child1Ref.current).toBe(container.getElementsByTagName('span')[0]);
1547 -
1548 - Scheduler.unstable_flushAll();
1549 -
1550 - expect(Scheduler).toHaveYielded([]);
1551 - });
1552 -
1553 - it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => {
1554 - let suspend = true;
1555 - let resolve;
1556 - const promise = new Promise(resolvePromise => (resolve = resolvePromise));
1557 -
1558 - function Child({text}) {
1559 - if (suspend) {
1560 - throw promise;
1561 - } else {
1562 - return text;
1563 - }
1564 - }
1565 -
1566 - function RenderedChild() {
1567 - useEffect(() => {
1568 - Scheduler.unstable_yieldValue('Child did commit');
1569 - });
1570 - return null;
1571 - }
1572 -
1573 - function App() {
1574 - const id = useOpaqueIdentifier();
1575 - useEffect(() => {
1576 - Scheduler.unstable_yieldValue('Did commit');
1577 - });
1578 - return (
1579 - <div>
1580 - <div id={id}>Child One</div>
1581 - <RenderedChild />
1582 - <React.Suspense fallback={'Fallback'}>
1583 - <div id={id}>
1584 - <Child text="Child Two" />
1585 - </div>
1586 - </React.Suspense>
1587 - </div>
1588 - );
1589 - }
1590 -
1591 - const container = document.createElement('div');
1592 - document.body.appendChild(container);
1593 -
1594 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1595 -
1596 - suspend = true;
1597 - const root = ReactDOM.createRoot(container, {hydrate: true});
1598 - await act(async () => {
1599 - root.render(<App />);
1600 - });
1601 - jest.runAllTimers();
1602 - expect(Scheduler).toHaveYielded(['Child did commit', 'Did commit']);
1603 - expect(Scheduler).toFlushAndYield([]);
1604 -
1605 - const serverId = container.children[0].children[0].getAttribute('id');
1606 - expect(container.children[0].children.length).toEqual(1);
1607 - expect(
1608 - container.children[0].children[0].getAttribute('id'),
1609 - ).not.toBeNull();
1610 -
1611 - await act(async () => {
1612 - suspend = false;
1613 - resolve();
1614 - await promise;
1615 - });
1616 -
1617 - expect(Scheduler).toHaveYielded(['Child did commit', 'Did commit']);
1618 - expect(Scheduler).toFlushAndYield([]);
1619 - jest.runAllTimers();
1620 -
1621 - expect(container.children[0].children.length).toEqual(2);
1622 - expect(container.children[0].children[0].getAttribute('id')).toEqual(
1623 - container.children[0].children[1].getAttribute('id'),
1624 - );
1625 - expect(container.children[0].children[0].getAttribute('id')).not.toEqual(
1626 - serverId,
1627 - );
1628 - expect(
1629 - container.children[0].children[0].getAttribute('id'),
1630 - ).not.toBeNull();
1631 - });
1632 -
1633 - it('useOpaqueIdentifier warn when there is a hydration error', async () => {
1634 - function Child({appId}) {
1635 - return <div aria-labelledby={appId} />;
1636 - }
1637 - function App() {
1638 - const id = useOpaqueIdentifier();
1639 - return <Child appId={id} />;
1640 - }
1641 -
1642 - const container = document.createElement('div');
1643 - document.body.appendChild(container);
1644 -
1645 - // This is the wrong HTML string
1646 - container.innerHTML = '<span></span>';
1647 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1648 - expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1649 - [
1650 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
1651 - 'Warning: Expected server HTML to contain a matching <div> in <div>.',
1652 - ],
1653 - {withoutStack: 1},
1654 - );
1655 - });
1656 -
1657 - it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => {
1658 - let suspend = true;
1659 -
1660 - function Child({text}) {
1661 - if (suspend) {
1662 - throw new Promise(() => {});
1663 - } else {
1664 - return text;
1665 - }
1666 - }
1667 -
1668 - function RenderedChild() {
1669 - useEffect(() => {
1670 - Scheduler.unstable_yieldValue('Child did commit');
1671 - });
1672 - return null;
1673 - }
1674 -
1675 - function App() {
1676 - const id = useOpaqueIdentifier();
1677 - useEffect(() => {
1678 - Scheduler.unstable_yieldValue('Did commit');
1679 - });
1680 - return (
1681 - <div>
1682 - <div id={id}>Child One</div>
1683 - <RenderedChild />
1684 - <React.Suspense fallback={'Fallback'}>
1685 - <div id={id}>
1686 - <Child text="Child Two" />
1687 - </div>
1688 - </React.Suspense>
1689 - </div>
1690 - );
1691 - }
1692 -
1693 - const container = document.createElement('div');
1694 - document.body.appendChild(container);
1695 -
1696 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1697 -
1698 - suspend = false;
1699 - const root = ReactDOM.createRoot(container, {hydrate: true});
1700 - await act(async () => {
1701 - root.render(<App />);
1702 - });
1703 - jest.runAllTimers();
1704 - expect(Scheduler).toHaveYielded([
1705 - 'Child did commit',
1706 - 'Did commit',
1707 - 'Child did commit',
1708 - 'Did commit',
1709 - ]);
1710 - expect(Scheduler).toFlushAndYield([]);
1711 -
1712 - expect(container.children[0].children.length).toEqual(2);
1713 - expect(container.children[0].children[0].getAttribute('id')).toEqual(
1714 - container.children[0].children[1].getAttribute('id'),
1715 - );
1716 - expect(
1717 - container.children[0].children[0].getAttribute('id'),
1718 - ).not.toBeNull();
1719 - });
1720 -
1721 - it('useOpaqueIdentifier warn when there is a hydration error', async () => {
1722 - function Child({appId}) {
1723 - return <div aria-labelledby={appId} />;
1724 - }
1725 - function App() {
1726 - const id = useOpaqueIdentifier();
1727 - return <Child appId={id} />;
1728 - }
1729 -
1730 - const container = document.createElement('div');
1731 - document.body.appendChild(container);
1732 -
1733 - // This is the wrong HTML string
1734 - container.innerHTML = '<span></span>';
1735 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1736 - expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1737 - [
1738 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
1739 - 'Warning: Expected server HTML to contain a matching <div> in <div>.',
1740 - ],
1741 - {withoutStack: 1},
1742 - );
1743 - });
1744 -
1745 - it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => {
1746 - function Child({appId}) {
1747 - return <div aria-labelledby={String(appId)} />;
1748 - }
1749 - function App() {
1750 - const id = useOpaqueIdentifier();
1751 - return <Child appId={id} />;
1752 - }
1753 -
1754 - const container = document.createElement('div');
1755 - document.body.appendChild(container);
1756 -
1757 - // This is the wrong HTML string
1758 - container.innerHTML = '<span></span>';
1759 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1760 - expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1761 - [
1762 - 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
1763 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
1764 - ],
1765 - {withoutStack: 1},
1766 - );
1767 - });
1768 -
1769 - it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => {
1770 - function Child({appId}) {
1771 - return <div aria-labelledby={String(appId)} />;
1772 - }
1773 - function App() {
1774 - const id = useOpaqueIdentifier();
1775 - return <Child appId={id} />;
1776 - }
1777 -
1778 - const container = document.createElement('div');
1779 - document.body.appendChild(container);
1780 -
1781 - // This is the wrong HTML string
1782 - container.innerHTML = '<span></span>';
1783 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1784 - expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1785 - [
1786 - 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
1787 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
1788 - ],
1789 - {withoutStack: 1},
1790 - );
1791 - });
1792 -
1793 - it('useOpaqueIdentifier warns if you try to use the result as a string in a child component', async () => {
1794 - function Child({appId}) {
1795 - return <div aria-labelledby={String(appId)} />;
1796 - }
1797 - function App() {
1798 - const id = useOpaqueIdentifier();
1799 - return <Child appId={id} />;
1800 - }
1801 -
1802 - const container = document.createElement('div');
1803 - document.body.appendChild(container);
1804 -
1805 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1806 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1807 - expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1808 - [
1809 - 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
1810 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
1811 - ],
1812 - {withoutStack: 1},
1813 - );
1814 - });
1815 -
1816 - it('useOpaqueIdentifier warns if you try to use the result as a string', async () => {
1817 - function App() {
1818 - const id = useOpaqueIdentifier();
1819 - return <div aria-labelledby={String(id)} />;
1820 - }
1821 -
1822 - const container = document.createElement('div');
1823 - document.body.appendChild(container);
1824 -
1825 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1826 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1827 - expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1828 - [
1829 - 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
1830 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
1831 - ],
1832 - {withoutStack: 1},
1833 - );
1834 - });
1835 -
1836 - it('useOpaqueIdentifier warns if you try to use the result as a string in a child component wrapped in a Suspense', async () => {
1837 - function Child({appId}) {
1838 - return <div aria-labelledby={String(appId)} />;
1839 - }
1840 - function App() {
1841 - const id = useOpaqueIdentifier();
1842 - return (
1843 - <React.Suspense fallback={null}>
1844 - <Child appId={id} />
1845 - </React.Suspense>
1846 - );
1847 - }
1848 -
1849 - const container = document.createElement('div');
1850 - document.body.appendChild(container);
1851 -
1852 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1853 -
1854 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1855 -
1856 - if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
1857 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
1858 - 'The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. ' +
1859 - 'Do not read the value directly.',
1860 - ]);
1861 - } else {
1862 - // This error isn't surfaced to the user; only the warning is.
1863 - // The error is just the mechanism that restarts the render.
1864 - expect(() =>
1865 - expect(() => Scheduler.unstable_flushAll()).toThrow(
1866 - 'The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. ' +
1867 - 'Do not read the value directly.',
1868 - ),
1869 - ).toErrorDev([
1870 - 'The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. ' +
1871 - 'Do not read the value directly.',
1872 - ]);
1873 - }
1874 - });
1875 -
1876 - it('useOpaqueIdentifier warns if you try to add the result as a number in a child component wrapped in a Suspense', async () => {
1877 - function Child({appId}) {
1878 - return <div aria-labelledby={+appId} />;
1879 - }
1880 - function App() {
1881 - const [show] = useState(false);
1882 - const id = useOpaqueIdentifier();
1883 - return (
1884 - <React.Suspense fallback={null}>
1885 - {show && <div id={id} />}
1886 - <Child appId={id} />
1887 - </React.Suspense>
1888 - );
1889 - }
1890 -
1891 - const container = document.createElement('div');
1892 - document.body.appendChild(container);
1893 -
1894 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1895 -
1896 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1897 -
1898 - if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
1899 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
1900 - 'The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. ' +
1901 - 'Do not read the value directly.',
1902 - ]);
1903 - } else {
1904 - // This error isn't surfaced to the user; only the warning is.
1905 - // The error is just the mechanism that restarts the render.
1906 - expect(() =>
1907 - expect(() => Scheduler.unstable_flushAll()).toThrow(
1908 - 'The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. ' +
1909 - 'Do not read the value directly.',
1910 - ),
1911 - ).toErrorDev([
1912 - 'The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. ' +
1913 - 'Do not read the value directly.',
1914 - ]);
1915 - }
1916 - });
1917 -
1918 - it('useOpaqueIdentifier with two opaque identifiers on the same page', () => {
1919 - let _setShow;
1920 -
1921 - function App() {
1922 - const id1 = useOpaqueIdentifier();
1923 - const id2 = useOpaqueIdentifier();
1924 - const [show, setShow] = useState(true);
1925 - _setShow = setShow;
1926 -
1927 - return (
1928 - <div>
1929 - <React.Suspense fallback={null}>
1930 - {show ? (
1931 - <span id={id1}>{'Child'}</span>
1932 - ) : (
1933 - <span id={id2}>{'Child'}</span>
1934 - )}
1935 - </React.Suspense>
1936 - <span aria-labelledby={id1}>{'test'}</span>
1937 - </div>
1938 - );
1939 - }
1940 -
1941 - const container = document.createElement('div');
1942 - document.body.appendChild(container);
1943 -
1944 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1945 -
1946 - const serverID = container
1947 - .getElementsByTagName('span')[0]
1948 - .getAttribute('id');
1949 - expect(serverID).not.toBeNull();
1950 - expect(
1951 - container
1952 - .getElementsByTagName('span')[1]
1953 - .getAttribute('aria-labelledby'),
1954 - ).toEqual(serverID);
1955 -
1956 - ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1957 - jest.runAllTimers();
1958 - expect(Scheduler).toHaveYielded([]);
1959 - expect(Scheduler).toFlushAndYield([]);
1960 -
1961 - act(() => {
1962 - _setShow(false);
1963 - });
1964 -
1965 - expect(
1966 - container
1967 - .getElementsByTagName('span')[1]
1968 - .getAttribute('aria-labelledby'),
1969 - ).toEqual(serverID);
1970 - expect(
1971 - container.getElementsByTagName('span')[0].getAttribute('id'),
1972 - ).not.toEqual(serverID);
1973 - expect(
1974 - container.getElementsByTagName('span')[0].getAttribute('id'),
1975 - ).not.toBeNull();
1976 - });
1977 -
1978 - it('useOpaqueIdentifier with multiple ids in nested components', async () => {
1979 - function DivWithId({id, children}) {
1980 - return <div id={id}>{children}</div>;
1981 - }
1982 -
1983 - let setShowMore;
1984 - function App() {
1985 - const outerId = useOpaqueIdentifier();
1986 - const innerId = useOpaqueIdentifier();
1987 - const [showMore, _setShowMore] = useState(false);
1988 - setShowMore = _setShowMore;
1989 - return showMore ? (
1990 - <DivWithId id={outerId}>
1991 - <DivWithId id={innerId} />
1992 - </DivWithId>
1993 - ) : null;
1994 - }
1995 -
1996 - const container = document.createElement('div');
1997 - container.innerHTML = ReactDOMServer.renderToString(<App />);
1998 -
1999 - await act(async () => {
2000 - ReactDOM.hydrateRoot(container, <App />);
2001 - });
2002 -
2003 - // Show additional content that wasn't part of the initial server-
2004 - // rendered repsonse.
2005 - await act(async () => {
2006 - setShowMore(true);
2007 - });
2008 - const [div1, div2] = container.getElementsByTagName('div');
2009 - expect(typeof div1.getAttribute('id')).toBe('string');
2010 - expect(typeof div2.getAttribute('id')).toBe('string');
2011 - });
2012 - });
904 });
packages/react-dom/src/client/DOMPropertyOperations.js
-8
@@ -21,7 +21,6 @@ import {
21 enableTrustedTypesIntegration,
22 } from 'shared/ReactFeatureFlags';
23 import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
24 -import {isOpaqueHydratingObject} from './ReactDOMHostConfig';
24
25 import type {PropertyInfo} from '../shared/DOMProperty';
26
@@ -119,13 +118,6 @@ export function getValueForAttribute(
118 if (!isAttributeNameSafe(name)) {
119 return;
120 }
122 -
123 - // If the object is an opaque reference ID, it's expected that
124 - // the next prop is different than the server value, so just return
125 - // expected
126 - if (isOpaqueHydratingObject(expected)) {
127 - return expected;
128 - }
121 if (!node.hasAttribute(name)) {
122 return expected === undefined ? undefined : null;
123 }
packages/react-dom/src/client/ReactDOMComponent.js
-10
@@ -68,7 +68,6 @@ import possibleStandardNames from '../shared/possibleStandardNames';
68 import {validateProperties as validateARIAProperties} from '../shared/ReactDOMInvalidARIAHook';
69 import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';
70 import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
71 -import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
71
72 import {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';
73 import {
@@ -775,15 +774,6 @@ export function diffProperties(
774 // to update this element.
775 updatePayload = [];
776 }
778 - } else if (
779 - typeof nextProp === 'object' &&
780 - nextProp !== null &&
781 - nextProp.$$typeof === REACT_OPAQUE_ID_TYPE
782 - ) {
783 - // If we encounter useOpaqueReference's opaque object, this means we are hydrating.
784 - // In this case, call the opaque object's toString function which generates a new client
785 - // ID so client and server IDs match and throws to rerender.
786 - nextProp.toString();
777 } else {
778 // For any other property we always add it to the queue and then we
779 // filter it out using the allowed property list during the commit.
packages/react-dom/src/client/ReactDOMHostConfig.js
-45
@@ -59,7 +59,6 @@ import {
59 } from '../shared/HTMLNodeType';
60 import dangerousStyleValue from '../shared/dangerousStyleValue';
61
62 -import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
62 import {retryIfBlockedOn} from '../events/ReactDOMEventReplaying';
63
64 import {
@@ -124,13 +123,6 @@ export type TimeoutHandle = TimeoutID;
123 export type NoTimeout = -1;
124 export type RendererInspectionConfig = $ReadOnly<{||}>;
125
127 -export opaque type OpaqueIDType =
128 - | string
129 - | {
130 - toString: () => string | void,
131 - valueOf: () => string | void,
132 - };
133 -
126 type SelectionInformation = {|
127 focusedElem: null | HTMLElement,
128 selectionRange: mixed,
@@ -1089,43 +1081,6 @@ export function getInstanceFromNode(node: HTMLElement): null | Object {
1081 return getClosestInstanceFromNode(node) || null;
1082 }
1083
1092 -let clientId: number = 0;
1093 -export function makeClientId(): OpaqueIDType {
1094 - return 'r:' + (clientId++).toString(36);
1095 -}
1096 -
1097 -export function makeClientIdInDEV(warnOnAccessInDEV: () => void): OpaqueIDType {
1098 - const id = 'r:' + (clientId++).toString(36);
1099 - return {
1100 - toString() {
1101 - warnOnAccessInDEV();
1102 - return id;
1103 - },
1104 - valueOf() {
1105 - warnOnAccessInDEV();
1106 - return id;
1107 - },
1108 - };
1109 -}
1110 -
1111 -export function isOpaqueHydratingObject(value: mixed): boolean {
1112 - return (
1113 - value !== null &&
1114 - typeof value === 'object' &&
1115 - value.$$typeof === REACT_OPAQUE_ID_TYPE
1116 - );
1117 -}
1118 -
1119 -export function makeOpaqueHydratingObject(
1120 - attemptToReadValue: () => void,
1121 -): OpaqueIDType {
1122 - return {
1123 - $$typeof: REACT_OPAQUE_ID_TYPE,
1124 - toString: attemptToReadValue,
1125 - valueOf: attemptToReadValue,
1126 - };
1127 -}
1128 -
1084 export function preparePortalMount(portalInstance: Instance): void {
1085 listenToAllSupportedEvents(portalInstance);
1086 }
packages/react-dom/src/server/ReactDOMServerFormatConfig.js
-22
@@ -64,9 +64,7 @@ export type ResponseState = {
64 placeholderPrefix: PrecomputedChunk,
65 segmentPrefix: PrecomputedChunk,
66 boundaryPrefix: string,
67 - opaqueIdentifierPrefix: string,
67 nextSuspenseID: number,
69 - nextOpaqueID: number,
68 sentCompleteSegmentFunction: boolean,
69 sentCompleteBoundaryFunction: boolean,
70 sentClientRenderFunction: boolean, // We allow the legacy renderer to extend this object.
@@ -127,9 +125,7 @@ export function createResponseState(
125 placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'),
126 segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'),
127 boundaryPrefix: idPrefix + 'B:',
130 - opaqueIdentifierPrefix: idPrefix + 'R:',
128 nextSuspenseID: 0,
132 - nextOpaqueID: 0,
129 sentCompleteSegmentFunction: false,
130 sentCompleteBoundaryFunction: false,
131 sentClientRenderFunction: false,
@@ -233,24 +229,6 @@ export function assignSuspenseBoundaryID(
229 );
230 }
231
236 -export type OpaqueIDType = string;
237 -
238 -export function makeServerID(
239 - responseState: null | ResponseState,
240 -): OpaqueIDType {
241 - if (responseState === null) {
242 - throw new Error(
243 - 'Invalid hook call. Hooks can only be called inside of the body of a function component.',
244 - );
245 - }
246 -
247 - // TODO: This is not deterministic since it's created during render.
248 - return (
249 - responseState.opaqueIdentifierPrefix +
250 - (responseState.nextOpaqueID++).toString(36)
251 - );
252 -}
253 -
232 function encodeHTMLTextNode(text: string): string {
233 return escapeTextForBrowser(text);
234 }
packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js
-6
@@ -34,9 +34,7 @@ export type ResponseState = {
34 placeholderPrefix: PrecomputedChunk,
35 segmentPrefix: PrecomputedChunk,
36 boundaryPrefix: string,
37 - opaqueIdentifierPrefix: string,
37 nextSuspenseID: number,
39 - nextOpaqueID: number,
38 sentCompleteSegmentFunction: boolean,
39 sentCompleteBoundaryFunction: boolean,
40 sentClientRenderFunction: boolean,
@@ -56,9 +54,7 @@ export function createResponseState(
54 placeholderPrefix: responseState.placeholderPrefix,
55 segmentPrefix: responseState.segmentPrefix,
56 boundaryPrefix: responseState.boundaryPrefix,
59 - opaqueIdentifierPrefix: responseState.opaqueIdentifierPrefix,
57 nextSuspenseID: responseState.nextSuspenseID,
61 - nextOpaqueID: responseState.nextOpaqueID,
58 sentCompleteSegmentFunction: responseState.sentCompleteSegmentFunction,
59 sentCompleteBoundaryFunction: responseState.sentCompleteBoundaryFunction,
60 sentClientRenderFunction: responseState.sentClientRenderFunction,
@@ -77,14 +73,12 @@ export function createRootFormatContext(): FormatContext {
73 export type {
74 FormatContext,
75 SuspenseBoundaryID,
80 - OpaqueIDType,
76 } from './ReactDOMServerFormatConfig';
77
78 export {
79 getChildFormatContext,
80 UNINITIALIZED_SUSPENSE_BOUNDARY_ID,
81 assignSuspenseBoundaryID,
87 - makeServerID,
82 pushStartInstance,
83 pushEndInstance,
84 pushStartCompletedSuspenseBoundary,
packages/react-dom/src/server/ReactPartialRenderer.js
+1 -16
@@ -82,10 +82,6 @@ import {validateProperties as validateInputProperties} from '../shared/ReactDOMN
82 import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
83 import hasOwnProperty from 'shared/hasOwnProperty';
84
85 -export type ServerOptions = {
86 - identifierPrefix?: string,
87 -};
88 -
85 // Based on reading the React.Children implementation. TODO: type this somewhere?
86 type ReactNode = string | number | ReactElement;
87 type FlatReactChildren = Array<null | ReactNode>;
@@ -784,14 +780,7 @@ class ReactDOMServerRenderer {
780 contextValueStack: Array<any>;
781 contextProviderStack: ?Array<ReactProvider<any>>; // DEV-only
782
787 - uniqueID: number;
788 - identifierPrefix: string;
789 -
790 - constructor(
791 - children: mixed,
792 - makeStaticMarkup: boolean,
793 - options?: ServerOptions,
794 - ) {
783 + constructor(children: mixed, makeStaticMarkup: boolean) {
784 const flatChildren = flattenTopLevelChildren(children);
785
786 const topFrame: Frame = {
@@ -820,10 +809,6 @@ class ReactDOMServerRenderer {
809 this.contextStack = [];
810 this.contextValueStack = [];
811
823 - // useOpaqueIdentifier ID
824 - this.uniqueID = 0;
825 - this.identifierPrefix = (options && options.identifierPrefix) || '';
826 -
812 if (__DEV__) {
813 this.contextProviderStack = [];
814 }
packages/react-dom/src/server/ReactPartialRendererHooks.js
+1 -12
@@ -41,8 +41,6 @@ type Hook = {|
41 next: Hook | null,
42 |};
43
44 -type OpaqueIDType = string;
45 -
44 let currentlyRenderingComponent: Object | null = null;
45 let firstWorkInProgressHook: Hook | null = null;
46 let workInProgressHook: Hook | null = null;
@@ -511,15 +509,7 @@ function useTransition(): [boolean, (callback: () => void) => void] {
509 return [false, startTransition];
510 }
511
514 -function useOpaqueIdentifier(): OpaqueIDType {
515 - return (
516 - (currentPartialRenderer.identifierPrefix || '') +
517 - 'R:' +
518 - (currentPartialRenderer.uniqueID++).toString(36)
519 - );
520 -}
521 -
522 -function useId(): OpaqueIDType {
512 +function useId(): string {
513 throw new Error('Not implemented.');
514 }
515
@@ -552,7 +542,6 @@ export const Dispatcher: DispatcherType = {
542 useDebugValue: noop,
543 useDeferredValue,
544 useTransition,
555 - useOpaqueIdentifier,
545 useId,
546 // Subscriptions are not setup in a server environment.
547 useMutableSource,
packages/react-native-renderer/src/ReactFabricHostConfig.js
-20
@@ -84,8 +84,6 @@ export type UpdatePayload = Object;
84 export type TimeoutHandle = TimeoutID;
85 export type NoTimeout = -1;
86
87 -export type OpaqueIDType = void;
88 -
87 export type RendererInspectionConfig = $ReadOnly<{|
88 // Deprecated. Replaced with getInspectorDataForViewAtPoint.
89 getInspectorDataForViewTag?: (tag: number) => Object,
@@ -512,24 +510,6 @@ export function getInstanceFromNode(node: any) {
510 throw new Error('Not yet implemented.');
511 }
512
515 -export function isOpaqueHydratingObject(value: mixed): boolean {
516 - throw new Error('Not yet implemented');
517 -}
518 -
519 -export function makeOpaqueHydratingObject(
520 - attemptToReadValue: () => void,
521 -): OpaqueIDType {
522 - throw new Error('Not yet implemented.');
523 -}
524 -
525 -export function makeClientId(): OpaqueIDType {
526 - throw new Error('Not yet implemented');
527 -}
528 -
529 -export function makeClientIdInDEV(warnOnAccessInDEV: () => void): OpaqueIDType {
530 - throw new Error('Not yet implemented');
531 -}
532 -
513 export function beforeActiveInstanceBlur(internalInstanceHandle: Object) {
514 // noop
515 }
packages/react-native-renderer/src/ReactNativeHostConfig.js
-19
@@ -43,7 +43,6 @@ export type ChildSet = void; // Unused
43
44 export type TimeoutHandle = TimeoutID;
45 export type NoTimeout = -1;
46 -export type OpaqueIDType = void;
46
47 export type RendererInspectionConfig = $ReadOnly<{|
48 // Deprecated. Replaced with getInspectorDataForViewAtPoint.
@@ -499,24 +498,6 @@ export function getInstanceFromNode(node: any) {
498 throw new Error('Not yet implemented.');
499 }
500
502 -export function isOpaqueHydratingObject(value: mixed): boolean {
503 - throw new Error('Not yet implemented');
504 -}
505 -
506 -export function makeOpaqueHydratingObject(
507 - attemptToReadValue: () => void,
508 -): OpaqueIDType {
509 - throw new Error('Not yet implemented.');
510 -}
511 -
512 -export function makeClientId(): OpaqueIDType {
513 - throw new Error('Not yet implemented');
514 -}
515 -
516 -export function makeClientIdInDEV(warnOnAccessInDEV: () => void): OpaqueIDType {
517 - throw new Error('Not yet implemented');
518 -}
519 -
501 export function beforeActiveInstanceBlur(internalInstanceHandle: Object) {
502 // noop
503 }
packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js
-17
@@ -59,14 +59,12 @@ SUSPENSE_UPDATE_TO_CLIENT_RENDER[0] = SUSPENSE_UPDATE_TO_CLIENT_RENDER_TAG;
59 // Per response,
60 export type ResponseState = {
61 nextSuspenseID: number,
62 - nextOpaqueID: number,
62 };
63
64 // Allows us to keep track of what we've already written so we can refer back to it.
65 export function createResponseState(): ResponseState {
66 return {
67 nextSuspenseID: 0,
69 - nextOpaqueID: 0,
68 };
69 }
70
@@ -109,21 +107,6 @@ export function assignSuspenseBoundaryID(
107 return responseState.nextSuspenseID++;
108 }
109
112 -export type OpaqueIDType = number;
113 -
114 -export function makeServerID(
115 - responseState: null | ResponseState,
116 -): OpaqueIDType {
117 - if (responseState === null) {
118 - throw new Error(
119 - 'Invalid hook call. Hooks can only be called inside of the body of a function component.',
120 - );
121 - }
122 -
123 - // TODO: This is not deterministic since it's created during render.
124 - return responseState.nextOpaqueID++;
125 -}
126 -
110 const RAW_TEXT = stringToPrecomputedChunk('RCTRawText');
111
112 export function pushTextInstance(
packages/react-noop-renderer/src/ReactNoopServer.js
-6
@@ -53,8 +53,6 @@ type Destination = {
53
54 const POP = Buffer.from('/', 'utf8');
55
56 -let opaqueID = 0;
57 -
56 const ReactNoopServer = ReactFizzServer({
57 scheduleWork(callback: () => void) {
58 callback();
@@ -88,10 +86,6 @@ const ReactNoopServer = ReactFizzServer({
86 return {state: 'pending', children: []};
87 },
88
91 - makeServerID(): number {
92 - return opaqueID++;
93 - },
94 -
89 getChildFormatContext(): null {
90 return null;
91 },
packages/react-reconciler/src/ReactFiberHooks.new.js
-139
@@ -17,7 +17,6 @@ import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes';
17 import type {Lanes, Lane} from './ReactFiberLane.new';
18 import type {HookFlags} from './ReactHookEffectTags';
19 import type {FiberRoot} from './ReactInternalTypes';
20 -import type {OpaqueIDType} from './ReactFiberHostConfig';
20 import type {Cache} from './ReactFiberCacheComponent.new';
21 import type {Flags} from './ReactFiberFlags';
22
@@ -95,18 +94,12 @@ import {
94 checkIfWorkInProgressReceivedUpdate,
95 } from './ReactFiberBeginWork.new';
96 import {getIsHydrating} from './ReactFiberHydrationContext.new';
98 -import {
99 - makeClientId,
100 - makeClientIdInDEV,
101 - makeOpaqueHydratingObject,
102 -} from './ReactFiberHostConfig';
97 import {
98 getWorkInProgressVersion,
99 markSourceAsDirty,
100 setWorkInProgressVersion,
101 warnAboutMultipleRenderersDEV,
102 } from './ReactMutableSource.new';
109 -import {getIsRendering} from './ReactCurrentFiber';
103 import {logStateUpdateScheduled} from './DebugTracing';
104 import {markStateUpdateScheduled} from './SchedulingProfiler';
105 import {createCache, CacheContext} from './ReactFiberCacheComponent.new';
@@ -139,10 +132,8 @@ export type UpdateQueue<S, A> = {|
132 |};
133
134 let didWarnAboutMismatchedHooksForComponent;
142 -let didWarnAboutUseOpaqueIdentifier;
135 let didWarnUncachedGetSnapshot;
136 if (__DEV__) {
145 - didWarnAboutUseOpaqueIdentifier = {};
137 didWarnAboutMismatchedHooksForComponent = new Set();
138 }
139
@@ -2045,94 +2036,6 @@ export function getIsUpdatingOpaqueValueInRenderPhaseInDEV(): boolean | void {
2036 }
2037 }
2038
2048 -function warnOnOpaqueIdentifierAccessInDEV(fiber) {
2049 - if (__DEV__) {
2050 - // TODO: Should warn in effects and callbacks, too
2051 - const name = getComponentNameFromFiber(fiber) || 'Unknown';
2052 - if (getIsRendering() && !didWarnAboutUseOpaqueIdentifier[name]) {
2053 - console.error(
2054 - 'The object passed back from useOpaqueIdentifier is meant to be ' +
2055 - 'passed through to attributes only. Do not read the ' +
2056 - 'value directly.',
2057 - );
2058 - didWarnAboutUseOpaqueIdentifier[name] = true;
2059 - }
2060 - }
2061 -}
2062 -
2063 -function mountOpaqueIdentifier(): OpaqueIDType | void {
2064 - const makeId = __DEV__
2065 - ? makeClientIdInDEV.bind(
2066 - null,
2067 - warnOnOpaqueIdentifierAccessInDEV.bind(null, currentlyRenderingFiber),
2068 - )
2069 - : makeClientId;
2070 -
2071 - if (getIsHydrating()) {
2072 - let didUpgrade = false;
2073 - const fiber = currentlyRenderingFiber;
2074 - const readValue = () => {
2075 - if (!didUpgrade) {
2076 - // Only upgrade once. This works even inside the render phase because
2077 - // the update is added to a shared queue, which outlasts the
2078 - // in-progress render.
2079 - didUpgrade = true;
2080 - if (__DEV__) {
2081 - isUpdatingOpaqueValueInRenderPhase = true;
2082 - setId(makeId());
2083 - isUpdatingOpaqueValueInRenderPhase = false;
2084 - warnOnOpaqueIdentifierAccessInDEV(fiber);
2085 - } else {
2086 - setId(makeId());
2087 - }
2088 - }
2089 -
2090 - throw new Error(
2091 - 'The object passed back from useOpaqueIdentifier is meant to be ' +
2092 - 'passed through to attributes only. Do not read the value directly.',
2093 - );
2094 - };
2095 - const id = makeOpaqueHydratingObject(readValue);
2096 -
2097 - const setId = mountState(id)[1];
2098 -
2099 - if ((currentlyRenderingFiber.mode & ConcurrentMode) === NoMode) {
2100 - if (
2101 - __DEV__ &&
2102 - enableStrictEffects &&
2103 - (currentlyRenderingFiber.mode & StrictEffectsMode) === NoMode
2104 - ) {
2105 - currentlyRenderingFiber.flags |= MountPassiveDevEffect | PassiveEffect;
2106 - } else {
2107 - currentlyRenderingFiber.flags |= PassiveEffect;
2108 - }
2109 - pushEffect(
2110 - HookHasEffect | HookPassive,
2111 - () => {
2112 - setId(makeId());
2113 - },
2114 - undefined,
2115 - null,
2116 - );
2117 - }
2118 - return id;
2119 - } else {
2120 - const id = makeId();
2121 - mountState(id);
2122 - return id;
2123 - }
2124 -}
2125 -
2126 -function updateOpaqueIdentifier(): OpaqueIDType | void {
2127 - const id = updateState(undefined)[0];
2128 - return id;
2129 -}
2130 -
2131 -function rerenderOpaqueIdentifier(): OpaqueIDType | void {
2132 - const id = rerenderState(undefined)[0];
2133 - return id;
2134 -}
2135 -
2039 function mountId(): string {
2040 const hook = mountWorkInProgressHook();
2041
@@ -2481,7 +2384,6 @@ export const ContextOnlyDispatcher: Dispatcher = {
2384 useTransition: throwInvalidHookError,
2385 useMutableSource: throwInvalidHookError,
2386 useSyncExternalStore: throwInvalidHookError,
2484 - useOpaqueIdentifier: throwInvalidHookError,
2387 useId: throwInvalidHookError,
2388
2389 unstable_isNewReconciler: enableNewReconciler,
@@ -2510,7 +2412,6 @@ const HooksDispatcherOnMount: Dispatcher = {
2412 useTransition: mountTransition,
2413 useMutableSource: mountMutableSource,
2414 useSyncExternalStore: mountSyncExternalStore,
2513 - useOpaqueIdentifier: mountOpaqueIdentifier,
2415 useId: mountId,
2416
2417 unstable_isNewReconciler: enableNewReconciler,
@@ -2539,7 +2440,6 @@ const HooksDispatcherOnUpdate: Dispatcher = {
2440 useTransition: updateTransition,
2441 useMutableSource: updateMutableSource,
2442 useSyncExternalStore: updateSyncExternalStore,
2542 - useOpaqueIdentifier: updateOpaqueIdentifier,
2443 useId: updateId,
2444
2445 unstable_isNewReconciler: enableNewReconciler,
@@ -2568,7 +2468,6 @@ const HooksDispatcherOnRerender: Dispatcher = {
2468 useTransition: rerenderTransition,
2469 useMutableSource: updateMutableSource,
2470 useSyncExternalStore: mountSyncExternalStore,
2571 - useOpaqueIdentifier: rerenderOpaqueIdentifier,
2471 useId: updateId,
2472
2473 unstable_isNewReconciler: enableNewReconciler,
@@ -2736,11 +2635,6 @@ if (__DEV__) {
2635 mountHookTypesDev();
2636 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2637 },
2739 - useOpaqueIdentifier(): OpaqueIDType | void {
2740 - currentHookNameInDev = 'useOpaqueIdentifier';
2741 - mountHookTypesDev();
2742 - return mountOpaqueIdentifier();
2743 - },
2638 useId(): string {
2639 currentHookNameInDev = 'useId';
2640 mountHookTypesDev();
@@ -2883,11 +2777,6 @@ if (__DEV__) {
2777 updateHookTypesDev();
2778 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2779 },
2886 - useOpaqueIdentifier(): OpaqueIDType | void {
2887 - currentHookNameInDev = 'useOpaqueIdentifier';
2888 - updateHookTypesDev();
2889 - return mountOpaqueIdentifier();
2890 - },
2780 useId(): string {
2781 currentHookNameInDev = 'useId';
2782 updateHookTypesDev();
@@ -3030,11 +2919,6 @@ if (__DEV__) {
2919 updateHookTypesDev();
2920 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2921 },
3033 - useOpaqueIdentifier(): OpaqueIDType | void {
3034 - currentHookNameInDev = 'useOpaqueIdentifier';
3035 - updateHookTypesDev();
3036 - return updateOpaqueIdentifier();
3037 - },
2922 useId(): string {
2923 currentHookNameInDev = 'useId';
2924 updateHookTypesDev();
@@ -3178,11 +3062,6 @@ if (__DEV__) {
3062 updateHookTypesDev();
3063 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3064 },
3181 - useOpaqueIdentifier(): OpaqueIDType | void {
3182 - currentHookNameInDev = 'useOpaqueIdentifier';
3183 - updateHookTypesDev();
3184 - return rerenderOpaqueIdentifier();
3185 - },
3065 useId(): string {
3066 currentHookNameInDev = 'useId';
3067 updateHookTypesDev();
@@ -3341,12 +3220,6 @@ if (__DEV__) {
3220 mountHookTypesDev();
3221 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3222 },
3344 - useOpaqueIdentifier(): OpaqueIDType | void {
3345 - currentHookNameInDev = 'useOpaqueIdentifier';
3346 - warnInvalidHookAccess();
3347 - mountHookTypesDev();
3348 - return mountOpaqueIdentifier();
3349 - },
3223 useId(): string {
3224 currentHookNameInDev = 'useId';
3225 warnInvalidHookAccess();
@@ -3506,12 +3379,6 @@ if (__DEV__) {
3379 updateHookTypesDev();
3380 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3381 },
3509 - useOpaqueIdentifier(): OpaqueIDType | void {
3510 - currentHookNameInDev = 'useOpaqueIdentifier';
3511 - warnInvalidHookAccess();
3512 - updateHookTypesDev();
3513 - return updateOpaqueIdentifier();
3514 - },
3382 useId(): string {
3383 currentHookNameInDev = 'useId';
3384 warnInvalidHookAccess();
@@ -3672,12 +3539,6 @@ if (__DEV__) {
3539 updateHookTypesDev();
3540 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3541 },
3675 - useOpaqueIdentifier(): OpaqueIDType | void {
3676 - currentHookNameInDev = 'useOpaqueIdentifier';
3677 - warnInvalidHookAccess();
3678 - updateHookTypesDev();
3679 - return rerenderOpaqueIdentifier();
3680 - },
3542 useId(): string {
3543 currentHookNameInDev = 'useId';
3544 warnInvalidHookAccess();
packages/react-reconciler/src/ReactFiberHooks.old.js
-139
@@ -17,7 +17,6 @@ import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes';
17 import type {Lanes, Lane} from './ReactFiberLane.old';
18 import type {HookFlags} from './ReactHookEffectTags';
19 import type {FiberRoot} from './ReactInternalTypes';
20 -import type {OpaqueIDType} from './ReactFiberHostConfig';
20 import type {Cache} from './ReactFiberCacheComponent.old';
21 import type {Flags} from './ReactFiberFlags';
22
@@ -95,18 +94,12 @@ import {
94 checkIfWorkInProgressReceivedUpdate,
95 } from './ReactFiberBeginWork.old';
96 import {getIsHydrating} from './ReactFiberHydrationContext.old';
98 -import {
99 - makeClientId,
100 - makeClientIdInDEV,
101 - makeOpaqueHydratingObject,
102 -} from './ReactFiberHostConfig';
97 import {
98 getWorkInProgressVersion,
99 markSourceAsDirty,
100 setWorkInProgressVersion,
101 warnAboutMultipleRenderersDEV,
102 } from './ReactMutableSource.old';
109 -import {getIsRendering} from './ReactCurrentFiber';
103 import {logStateUpdateScheduled} from './DebugTracing';
104 import {markStateUpdateScheduled} from './SchedulingProfiler';
105 import {createCache, CacheContext} from './ReactFiberCacheComponent.old';
@@ -139,10 +132,8 @@ export type UpdateQueue<S, A> = {|
132 |};
133
134 let didWarnAboutMismatchedHooksForComponent;
142 -let didWarnAboutUseOpaqueIdentifier;
135 let didWarnUncachedGetSnapshot;
136 if (__DEV__) {
145 - didWarnAboutUseOpaqueIdentifier = {};
137 didWarnAboutMismatchedHooksForComponent = new Set();
138 }
139
@@ -2045,94 +2036,6 @@ export function getIsUpdatingOpaqueValueInRenderPhaseInDEV(): boolean | void {
2036 }
2037 }
2038
2048 -function warnOnOpaqueIdentifierAccessInDEV(fiber) {
2049 - if (__DEV__) {
2050 - // TODO: Should warn in effects and callbacks, too
2051 - const name = getComponentNameFromFiber(fiber) || 'Unknown';
2052 - if (getIsRendering() && !didWarnAboutUseOpaqueIdentifier[name]) {
2053 - console.error(
2054 - 'The object passed back from useOpaqueIdentifier is meant to be ' +
2055 - 'passed through to attributes only. Do not read the ' +
2056 - 'value directly.',
2057 - );
2058 - didWarnAboutUseOpaqueIdentifier[name] = true;
2059 - }
2060 - }
2061 -}
2062 -
2063 -function mountOpaqueIdentifier(): OpaqueIDType | void {
2064 - const makeId = __DEV__
2065 - ? makeClientIdInDEV.bind(
2066 - null,
2067 - warnOnOpaqueIdentifierAccessInDEV.bind(null, currentlyRenderingFiber),
2068 - )
2069 - : makeClientId;
2070 -
2071 - if (getIsHydrating()) {
2072 - let didUpgrade = false;
2073 - const fiber = currentlyRenderingFiber;
2074 - const readValue = () => {
2075 - if (!didUpgrade) {
2076 - // Only upgrade once. This works even inside the render phase because
2077 - // the update is added to a shared queue, which outlasts the
2078 - // in-progress render.
2079 - didUpgrade = true;
2080 - if (__DEV__) {
2081 - isUpdatingOpaqueValueInRenderPhase = true;
2082 - setId(makeId());
2083 - isUpdatingOpaqueValueInRenderPhase = false;
2084 - warnOnOpaqueIdentifierAccessInDEV(fiber);
2085 - } else {
2086 - setId(makeId());
2087 - }
2088 - }
2089 -
2090 - throw new Error(
2091 - 'The object passed back from useOpaqueIdentifier is meant to be ' +
2092 - 'passed through to attributes only. Do not read the value directly.',
2093 - );
2094 - };
2095 - const id = makeOpaqueHydratingObject(readValue);
2096 -
2097 - const setId = mountState(id)[1];
2098 -
2099 - if ((currentlyRenderingFiber.mode & ConcurrentMode) === NoMode) {
2100 - if (
2101 - __DEV__ &&
2102 - enableStrictEffects &&
2103 - (currentlyRenderingFiber.mode & StrictEffectsMode) === NoMode
2104 - ) {
2105 - currentlyRenderingFiber.flags |= MountPassiveDevEffect | PassiveEffect;
2106 - } else {
2107 - currentlyRenderingFiber.flags |= PassiveEffect;
2108 - }
2109 - pushEffect(
2110 - HookHasEffect | HookPassive,
2111 - () => {
2112 - setId(makeId());
2113 - },
2114 - undefined,
2115 - null,
2116 - );
2117 - }
2118 - return id;
2119 - } else {
2120 - const id = makeId();
2121 - mountState(id);
2122 - return id;
2123 - }
2124 -}
2125 -
2126 -function updateOpaqueIdentifier(): OpaqueIDType | void {
2127 - const id = updateState(undefined)[0];
2128 - return id;
2129 -}
2130 -
2131 -function rerenderOpaqueIdentifier(): OpaqueIDType | void {
2132 - const id = rerenderState(undefined)[0];
2133 - return id;
2134 -}
2135 -
2039 function mountId(): string {
2040 const hook = mountWorkInProgressHook();
2041
@@ -2481,7 +2384,6 @@ export const ContextOnlyDispatcher: Dispatcher = {
2384 useTransition: throwInvalidHookError,
2385 useMutableSource: throwInvalidHookError,
2386 useSyncExternalStore: throwInvalidHookError,
2484 - useOpaqueIdentifier: throwInvalidHookError,
2387 useId: throwInvalidHookError,
2388
2389 unstable_isNewReconciler: enableNewReconciler,
@@ -2510,7 +2412,6 @@ const HooksDispatcherOnMount: Dispatcher = {
2412 useTransition: mountTransition,
2413 useMutableSource: mountMutableSource,
2414 useSyncExternalStore: mountSyncExternalStore,
2513 - useOpaqueIdentifier: mountOpaqueIdentifier,
2415 useId: mountId,
2416
2417 unstable_isNewReconciler: enableNewReconciler,
@@ -2539,7 +2440,6 @@ const HooksDispatcherOnUpdate: Dispatcher = {
2440 useTransition: updateTransition,
2441 useMutableSource: updateMutableSource,
2442 useSyncExternalStore: updateSyncExternalStore,
2542 - useOpaqueIdentifier: updateOpaqueIdentifier,
2443 useId: updateId,
2444
2445 unstable_isNewReconciler: enableNewReconciler,
@@ -2568,7 +2468,6 @@ const HooksDispatcherOnRerender: Dispatcher = {
2468 useTransition: rerenderTransition,
2469 useMutableSource: updateMutableSource,
2470 useSyncExternalStore: mountSyncExternalStore,
2571 - useOpaqueIdentifier: rerenderOpaqueIdentifier,
2471 useId: updateId,
2472
2473 unstable_isNewReconciler: enableNewReconciler,
@@ -2736,11 +2635,6 @@ if (__DEV__) {
2635 mountHookTypesDev();
2636 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2637 },
2739 - useOpaqueIdentifier(): OpaqueIDType | void {
2740 - currentHookNameInDev = 'useOpaqueIdentifier';
2741 - mountHookTypesDev();
2742 - return mountOpaqueIdentifier();
2743 - },
2638 useId(): string {
2639 currentHookNameInDev = 'useId';
2640 mountHookTypesDev();
@@ -2883,11 +2777,6 @@ if (__DEV__) {
2777 updateHookTypesDev();
2778 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2779 },
2886 - useOpaqueIdentifier(): OpaqueIDType | void {
2887 - currentHookNameInDev = 'useOpaqueIdentifier';
2888 - updateHookTypesDev();
2889 - return mountOpaqueIdentifier();
2890 - },
2780 useId(): string {
2781 currentHookNameInDev = 'useId';
2782 updateHookTypesDev();
@@ -3030,11 +2919,6 @@ if (__DEV__) {
2919 updateHookTypesDev();
2920 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2921 },
3033 - useOpaqueIdentifier(): OpaqueIDType | void {
3034 - currentHookNameInDev = 'useOpaqueIdentifier';
3035 - updateHookTypesDev();
3036 - return updateOpaqueIdentifier();
3037 - },
2922 useId(): string {
2923 currentHookNameInDev = 'useId';
2924 updateHookTypesDev();
@@ -3178,11 +3062,6 @@ if (__DEV__) {
3062 updateHookTypesDev();
3063 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3064 },
3181 - useOpaqueIdentifier(): OpaqueIDType | void {
3182 - currentHookNameInDev = 'useOpaqueIdentifier';
3183 - updateHookTypesDev();
3184 - return rerenderOpaqueIdentifier();
3185 - },
3065 useId(): string {
3066 currentHookNameInDev = 'useId';
3067 updateHookTypesDev();
@@ -3341,12 +3220,6 @@ if (__DEV__) {
3220 mountHookTypesDev();
3221 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3222 },
3344 - useOpaqueIdentifier(): OpaqueIDType | void {
3345 - currentHookNameInDev = 'useOpaqueIdentifier';
3346 - warnInvalidHookAccess();
3347 - mountHookTypesDev();
3348 - return mountOpaqueIdentifier();
3349 - },
3223 useId(): string {
3224 currentHookNameInDev = 'useId';
3225 warnInvalidHookAccess();
@@ -3506,12 +3379,6 @@ if (__DEV__) {
3379 updateHookTypesDev();
3380 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3381 },
3509 - useOpaqueIdentifier(): OpaqueIDType | void {
3510 - currentHookNameInDev = 'useOpaqueIdentifier';
3511 - warnInvalidHookAccess();
3512 - updateHookTypesDev();
3513 - return updateOpaqueIdentifier();
3514 - },
3382 useId(): string {
3383 currentHookNameInDev = 'useId';
3384 warnInvalidHookAccess();
@@ -3672,12 +3539,6 @@ if (__DEV__) {
3539 updateHookTypesDev();
3540 return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3541 },
3675 - useOpaqueIdentifier(): OpaqueIDType | void {
3676 - currentHookNameInDev = 'useOpaqueIdentifier';
3677 - warnInvalidHookAccess();
3678 - updateHookTypesDev();
3679 - return rerenderOpaqueIdentifier();
3680 - },
3542 useId(): string {
3543 currentHookNameInDev = 'useId';
3544 warnInvalidHookAccess();
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+5 -8
@@ -474,8 +474,7 @@ export function scheduleUpdateOnFiber(
474 // if the update originates from user space (with the exception of local
475 // hook updates, which are handled differently and don't reach this
476 // function), but there are some internal React features that use this as
477 - // an implementation detail, like selective hydration
478 - // and useOpaqueIdentifier.
477 + // an implementation detail, like selective hydration.
478 warnAboutRenderPhaseUpdatesInDEV(fiber);
479
480 // Track lanes that were updated during the render phase
@@ -898,12 +897,10 @@ function recoverFromConcurrentError(root, errorRetryLanes) {
897 exitStatus === RootErrored &&
898 workInProgressRootRenderPhaseUpdatedLanes !== NoLanes
899 ) {
901 - // There was a render phase update during this render. This was likely a
902 - // useOpaqueIdentifier hook upgrading itself to a client ID. Try rendering
903 - // again. This time, the component will use a client ID and will proceed
904 - // without throwing. If multiple IDs upgrade as a result of the same
905 - // update, we will have to do multiple render passes. To protect against
906 - // an inifinite loop, eventually we'll give up.
900 + // There was a render phase update during this render. Some internal React
901 + // implementation details may use this as a trick to schedule another
902 + // render pass. To protect against an inifinite loop, eventually
903 + // we'll give up.
904 continue;
905 }
906 break;
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+5 -8
@@ -474,8 +474,7 @@ export function scheduleUpdateOnFiber(
474 // if the update originates from user space (with the exception of local
475 // hook updates, which are handled differently and don't reach this
476 // function), but there are some internal React features that use this as
477 - // an implementation detail, like selective hydration
478 - // and useOpaqueIdentifier.
477 + // an implementation detail, like selective hydration.
478 warnAboutRenderPhaseUpdatesInDEV(fiber);
479
480 // Track lanes that were updated during the render phase
@@ -898,12 +897,10 @@ function recoverFromConcurrentError(root, errorRetryLanes) {
897 exitStatus === RootErrored &&
898 workInProgressRootRenderPhaseUpdatedLanes !== NoLanes
899 ) {
901 - // There was a render phase update during this render. This was likely a
902 - // useOpaqueIdentifier hook upgrading itself to a client ID. Try rendering
903 - // again. This time, the component will use a client ID and will proceed
904 - // without throwing. If multiple IDs upgrade as a result of the same
905 - // update, we will have to do multiple render passes. To protect against
906 - // an inifinite loop, eventually we'll give up.
900 + // There was a render phase update during this render. Some internal React
901 + // implementation details may use this as a trick to schedule another
902 + // render pass. To protect against an inifinite loop, eventually
903 + // we'll give up.
904 continue;
905 }
906 break;
packages/react-reconciler/src/ReactInternalTypes.js
-2
@@ -43,7 +43,6 @@ export type HookType =
43 | 'useTransition'
44 | 'useMutableSource'
45 | 'useSyncExternalStore'
46 - | 'useOpaqueIdentifier'
46 | 'useId'
47 | 'useCacheRefresh';
48
@@ -317,7 +316,6 @@ export type Dispatcher = {|
316 getSnapshot: () => T,
317 getServerSnapshot?: () => T,
318 ): T,
320 - useOpaqueIdentifier(): any,
319 useId(): string,
320 useCacheRefresh?: () => <T>(?() => T, ?T) => void,
321
packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js
+8 -8
@@ -1916,14 +1916,14 @@ describe('ReactIncrementalErrorHandling', () => {
1916 });
1917
1918 it("does not infinite loop if there's a render phase update in the same render as an error", async () => {
1919 - // useOpaqueIdentifier uses an render phase update as an implementation
1920 - // detail. When an error is accompanied by a render phase update, we assume
1921 - // that it comes from useOpaqueIdentifier, because render phase updates
1922 - // triggered from userspace are not allowed (we log a warning). So we keep
1923 - // attempting to recover until no more opaque identifiers need to be
1924 - // upgraded. However, we should give up after some point to prevent an
1925 - // infinite loop in the case where there is (by accident) a render phase
1926 - // triggered from userspace.
1919 + // Some React features may schedule a render phase update as an
1920 + // implementation detail. When an error is accompanied by a render phase
1921 + // update, we assume that it comes from React internals, because render
1922 + // phase updates triggered from userspace are not allowed (we log a
1923 + // warning). So we keep attempting to recover until no more opaque
1924 + // identifiers need to be upgraded. However, we should give up after some
1925 + // point to prevent an infinite loop in the case where there is (by
1926 + // accident) a render phase triggered from userspace.
1927
1928 spyOnDev(console, 'error');
1929
packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js
-6
@@ -38,7 +38,6 @@ export opaque type ChildSet = mixed; // eslint-disable-line no-undef
38 export opaque type TimeoutHandle = mixed; // eslint-disable-line no-undef
39 export opaque type NoTimeout = mixed; // eslint-disable-line no-undef
40 export opaque type RendererInspectionConfig = mixed; // eslint-disable-line no-undef
41 -export opaque type OpaqueIDType = mixed;
41 export type EventResponder = any;
42
43 export const getPublicInstance = $$$hostConfig.getPublicInstance;
@@ -62,11 +61,6 @@ export const supportsMutation = $$$hostConfig.supportsMutation;
61 export const supportsPersistence = $$$hostConfig.supportsPersistence;
62 export const supportsHydration = $$$hostConfig.supportsHydration;
63 export const getInstanceFromNode = $$$hostConfig.getInstanceFromNode;
65 -export const isOpaqueHydratingObject = $$$hostConfig.isOpaqueHydratingObject;
66 -export const makeOpaqueHydratingObject =
67 - $$$hostConfig.makeOpaqueHydratingObject;
68 -export const makeClientId = $$$hostConfig.makeClientId;
69 -export const makeClientIdInDEV = $$$hostConfig.makeClientIdInDEV;
64 export const beforeActiveInstanceBlur = $$$hostConfig.beforeActiveInstanceBlur;
65 export const afterActiveInstanceBlur = $$$hostConfig.afterActiveInstanceBlur;
66 export const preparePortalMount = $$$hostConfig.preparePortalMount;
packages/react-server/src/ReactFizzHooks.js
+1 -8
@@ -16,14 +16,12 @@ import type {
16 ReactContext,
17 } from 'shared/ReactTypes';
18
19 -import type {ResponseState, OpaqueIDType} from './ReactServerFormatConfig';
19 +import type {ResponseState} from './ReactServerFormatConfig';
20 import type {Task} from './ReactFizzServer';
21
22 import {readContext as readContextImpl} from './ReactFizzNewContext';
23 import {getTreeId} from './ReactFizzTreeContext';
24
25 -import {makeServerID} from './ReactServerFormatConfig';
26 -
25 import {enableCache} from 'shared/ReactFeatureFlags';
26 import is from 'shared/objectIs';
27
@@ -509,10 +507,6 @@ function useTransition(): [boolean, (callback: () => void) => void] {
507 return [false, unsupportedStartTransition];
508 }
509
512 -function useOpaqueIdentifier(): OpaqueIDType {
513 - return makeServerID(currentResponseState);
514 -}
515 -
510 function useId(): string {
511 const task: Task = (currentlyRenderingTask: any);
512 const treeId = getTreeId(task.treeContext);
@@ -559,7 +553,6 @@ export const Dispatcher: DispatcherType = {
553 useDebugValue: noop,
554 useDeferredValue,
555 useTransition,
562 - useOpaqueIdentifier,
556 useId,
557 // Subscriptions are not setup in a server environment.
558 useMutableSource,
packages/react-server/src/ReactFlightServer.js
-1
@@ -845,7 +845,6 @@ const Dispatcher: DispatcherType = {
845 useLayoutEffect: (unsupportedHook: any),
846 useImperativeHandle: (unsupportedHook: any),
847 useEffect: (unsupportedHook: any),
848 - useOpaqueIdentifier: (unsupportedHook: any),
848 useId: (unsupportedHook: any),
849 useMutableSource: (unsupportedHook: any),
850 useSyncExternalStore: (unsupportedHook: any),
packages/react-server/src/forks/ReactServerFormatConfig.custom.js
-2
@@ -28,7 +28,6 @@ export opaque type Destination = mixed; // eslint-disable-line no-undef
28 export opaque type ResponseState = mixed;
29 export opaque type FormatContext = mixed;
30 export opaque type SuspenseBoundaryID = mixed;
31 -export opaque type OpaqueIDType = mixed;
31
32 export const isPrimaryRenderer = false;
33
@@ -36,7 +35,6 @@ export const getChildFormatContext = $$$hostConfig.getChildFormatContext;
35 export const UNINITIALIZED_SUSPENSE_BOUNDARY_ID =
36 $$$hostConfig.UNINITIALIZED_SUSPENSE_BOUNDARY_ID;
37 export const assignSuspenseBoundaryID = $$$hostConfig.assignSuspenseBoundaryID;
39 -export const makeServerID = $$$hostConfig.makeServerID;
38 export const pushTextInstance = $$$hostConfig.pushTextInstance;
39 export const pushStartInstance = $$$hostConfig.pushStartInstance;
40 export const pushEndInstance = $$$hostConfig.pushEndInstance;
packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js
-1
@@ -42,7 +42,6 @@ export function waitForSuspense<T>(fn: () => T): Promise<T> {
42 useDebugValue: unsupported,
43 useDeferredValue: unsupported,
44 useTransition: unsupported,
45 - useOpaqueIdentifier: unsupported,
45 useId: unsupported,
46 useMutableSource: unsupported,
47 useSyncExternalStore: unsupported,
packages/react-test-renderer/src/ReactTestHostConfig.js
-44
@@ -7,7 +7,6 @@
7 * @flow
8 */
9
10 -import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
10 import isArray from 'shared/isArray';
11 import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
12
@@ -40,12 +39,6 @@ export type ChildSet = void; // Unused
39 export type TimeoutHandle = TimeoutID;
40 export type NoTimeout = -1;
41 export type EventResponder = any;
43 -export opaque type OpaqueIDType =
44 - | string
45 - | {
46 - toString: () => string | void,
47 - valueOf: () => string | void,
48 - };
42
43 export type RendererInspectionConfig = $ReadOnly<{||}>;
44
@@ -298,43 +291,6 @@ export function getInstanceFromNode(mockNode: Object) {
291 return null;
292 }
293
301 -let clientId: number = 0;
302 -export function makeClientId(): OpaqueIDType {
303 - return 'c_' + (clientId++).toString(36);
304 -}
305 -
306 -export function makeClientIdInDEV(warnOnAccessInDEV: () => void): OpaqueIDType {
307 - const id = 'c_' + (clientId++).toString(36);
308 - return {
309 - toString() {
310 - warnOnAccessInDEV();
311 - return id;
312 - },
313 - valueOf() {
314 - warnOnAccessInDEV();
315 - return id;
316 - },
317 - };
318 -}
319 -
320 -export function isOpaqueHydratingObject(value: mixed): boolean {
321 - return (
322 - value !== null &&
323 - typeof value === 'object' &&
324 - value.$$typeof === REACT_OPAQUE_ID_TYPE
325 - );
326 -}
327 -
328 -export function makeOpaqueHydratingObject(
329 - attemptToReadValue: () => void,
330 -): OpaqueIDType {
331 - return {
332 - $$typeof: REACT_OPAQUE_ID_TYPE,
333 - toString: attemptToReadValue,
334 - valueOf: attemptToReadValue,
335 - };
336 -}
337 -
294 export function beforeActiveInstanceBlur(internalInstanceHandle: Object) {
295 // noop
296 }
packages/react/index.classic.fb.js
-1
@@ -40,7 +40,6 @@ export {
40 unstable_getCacheSignal,
41 unstable_getCacheForType,
42 unstable_useCacheRefresh,
43 - unstable_useOpaqueIdentifier,
43 unstable_useId,
44 useCallback,
45 useContext,
packages/react/index.experimental.js
-1
@@ -36,7 +36,6 @@ export {
36 unstable_getCacheSignal,
37 unstable_getCacheForType,
38 unstable_useCacheRefresh,
39 - unstable_useOpaqueIdentifier,
39 unstable_useId,
40 useCallback,
41 useContext,
packages/react/index.js
-1
@@ -61,7 +61,6 @@ export {
61 unstable_getCacheSignal,
62 unstable_getCacheForType,
63 unstable_useCacheRefresh,
64 - unstable_useOpaqueIdentifier,
64 unstable_useId,
65 useCallback,
66 useContext,
packages/react/index.modern.fb.js
-1
@@ -39,7 +39,6 @@ export {
39 unstable_getCacheSignal,
40 unstable_getCacheForType,
41 unstable_useCacheRefresh,
42 - unstable_useOpaqueIdentifier,
42 unstable_useId,
43 useCallback,
44 useContext,
packages/react/index.stable.js
-1
@@ -29,7 +29,6 @@ export {
29 lazy,
30 memo,
31 startTransition,
32 - unstable_useOpaqueIdentifier,
32 unstable_useId,
33 useCallback,
34 useContext,
packages/react/src/React.js
-2
@@ -52,7 +52,6 @@ import {
52 useState,
53 useTransition,
54 useDeferredValue,
55 - useOpaqueIdentifier,
55 useId,
56 useCacheRefresh,
57 } from './ReactHooks';
@@ -127,7 +126,6 @@ export {
126 REACT_CACHE_TYPE as unstable_Cache,
127 // enableScopeAPI
128 REACT_SCOPE_TYPE as unstable_Scope,
130 - useOpaqueIdentifier as unstable_useOpaqueIdentifier,
129 useId as unstable_useId,
130 act,
131 };
packages/react/src/ReactHooks.js
-6
@@ -14,7 +14,6 @@ import type {
14 MutableSourceSubscribeFn,
15 ReactContext,
16 } from 'shared/ReactTypes';
17 -import type {OpaqueIDType} from 'react-reconciler/src/ReactFiberHostConfig';
17
18 import ReactCurrentDispatcher from './ReactCurrentDispatcher';
19
@@ -169,11 +168,6 @@ export function useDeferredValue<T>(value: T): T {
168 return dispatcher.useDeferredValue(value);
169 }
170
172 -export function useOpaqueIdentifier(): OpaqueIDType | void {
173 - const dispatcher = resolveDispatcher();
174 - return dispatcher.useOpaqueIdentifier();
175 -}
176 -
171 export function useId(): string {
172 const dispatcher = resolveDispatcher();
173 return dispatcher.useId();
packages/react/unstable-shared-subset.experimental.js
-1
@@ -27,7 +27,6 @@ export {
27 unstable_DebugTracingMode,
28 unstable_getCacheSignal,
29 unstable_getCacheForType,
30 - unstable_useOpaqueIdentifier,
30 unstable_useId,
31 useCallback,
32 useContext,
packages/shared/CheckStringCoercion.js
-12
@@ -7,8 +7,6 @@
7 * @flow
8 */
9
10 -import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
11 -
10 /*
11 * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol
12 * and Temporal.* types. See https://github.com/facebook/react/pull/22064.
@@ -35,16 +33,6 @@ function typeName(value: mixed): string {
33 // $FlowFixMe only called in DEV, so void return is not possible.
34 function willCoercionThrow(value: mixed): boolean {
35 if (__DEV__) {
38 - if (
39 - value !== null &&
40 - typeof value === 'object' &&
41 - value.$$typeof === REACT_OPAQUE_ID_TYPE
42 - ) {
43 - // OpaqueID type is expected to throw, so React will handle it. Not sure if
44 - // it's expected that string coercion will throw, but we'll assume it's OK.
45 - // See https://github.com/facebook/react/issues/20127.
46 - return;
47 - }
36 try {
37 testStringCoercion(value);
38 return false;
packages/shared/ReactSymbols.js
-2
@@ -26,7 +26,6 @@ export let REACT_SUSPENSE_LIST_TYPE = 0xead8;
26 export let REACT_MEMO_TYPE = 0xead3;
27 export let REACT_LAZY_TYPE = 0xead4;
28 export let REACT_SCOPE_TYPE = 0xead7;
29 -export let REACT_OPAQUE_ID_TYPE = 0xeae0;
29 export let REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;
30 export let REACT_OFFSCREEN_TYPE = 0xeae2;
31 export let REACT_LEGACY_HIDDEN_TYPE = 0xeae3;
@@ -47,7 +46,6 @@ if (typeof Symbol === 'function' && Symbol.for) {
46 REACT_MEMO_TYPE = symbolFor('react.memo');
47 REACT_LAZY_TYPE = symbolFor('react.lazy');
48 REACT_SCOPE_TYPE = symbolFor('react.scope');
50 - REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');
49 REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');
50 REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');
51 REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');
scripts/error-codes/codes.json
+1 -1
@@ -342,7 +342,7 @@
342 "352": "React Lazy Components are not yet supported on the server.",
343 "353": "A server block should never encode any other slots. This is a bug in React.",
344 "354": "getInspectorDataForViewAtPoint() is not available in production.",
345 - "355": "The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.",
345 + "355": "The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly. (TODO: This feature was never released so we should be able to remove this error from the map.)",
346 "356": "Could not read the cache.",
347 "357": "The current renderer does not support React Scopes. This error is likely caused by a bug in React. Please file an issue.",
348 "358": "Invalid update priority: %s. This is a bug in React.",