Best JavaScript code snippet using playwright-internal
ReactFiberHooks.js
Source:ReactFiberHooks.js
...747 create,748 deps,749 );750}751function mountLayoutEffect(752 create: () => (() => void) | void,753 deps: Array<mixed> | void | null,754): void {755 return mountEffectImpl(756 UpdateEffect,757 UnmountMutation | MountLayout,758 create,759 deps,760 );761}762function updateLayoutEffect(763 create: () => (() => void) | void,764 deps: Array<mixed> | void | null,765): void {766 return updateEffectImpl(767 UpdateEffect,768 UnmountMutation | MountLayout,769 create,770 deps,771 );772}773function imperativeHandleEffect<T>(774 create: () => T,775 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,776) {777 if (typeof ref === 'function') {778 const refCallback = ref;779 const inst = create();780 refCallback(inst);781 return () => {782 refCallback(null);783 };784 } else if (ref !== null && ref !== undefined) {785 const refObject = ref;786 if (__DEV__) {787 warning(788 refObject.hasOwnProperty('current'),789 'Expected useImperativeHandle() first argument to either be a ' +790 'ref callback or React.createRef() object. Instead received: %s.',791 'an object with keys {' + Object.keys(refObject).join(', ') + '}',792 );793 }794 const inst = create();795 refObject.current = inst;796 return () => {797 refObject.current = null;798 };799 }800}801function mountImperativeHandle<T>(802 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,803 create: () => T,804 deps: Array<mixed> | void | null,805): void {806 if (__DEV__) {807 warning(808 typeof create === 'function',809 'Expected useImperativeHandle() second argument to be a function ' +810 'that creates a handle. Instead received: %s.',811 create !== null ? typeof create : 'null',812 );813 }814 // TODO: If deps are provided, should we skip comparing the ref itself?815 const effectDeps =816 deps !== null && deps !== undefined ? deps.concat([ref]) : null;817 return mountEffectImpl(818 UpdateEffect,819 UnmountMutation | MountLayout,820 imperativeHandleEffect.bind(null, create, ref),821 effectDeps,822 );823}824function updateImperativeHandle<T>(825 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,826 create: () => T,827 deps: Array<mixed> | void | null,828): void {829 if (__DEV__) {830 warning(831 typeof create === 'function',832 'Expected useImperativeHandle() second argument to be a function ' +833 'that creates a handle. Instead received: %s.',834 create !== null ? typeof create : 'null',835 );836 }837 // TODO: If deps are provided, should we skip comparing the ref itself?838 const effectDeps =839 deps !== null && deps !== undefined ? deps.concat([ref]) : null;840 return updateEffectImpl(841 UpdateEffect,842 UnmountMutation | MountLayout,843 imperativeHandleEffect.bind(null, create, ref),844 effectDeps,845 );846}847function mountDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {848 // This hook is normally a no-op.849 // The react-debug-hooks package injects its own implementation850 // so that e.g. DevTools can display custom hook values.851}852const updateDebugValue = mountDebugValue;853function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {854 const hook = mountWorkInProgressHook();855 const nextDeps = deps === undefined ? null : deps;856 hook.memoizedState = [callback, nextDeps];857 return callback;858}859function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {860 const hook = updateWorkInProgressHook();861 const nextDeps = deps === undefined ? null : deps;862 const prevState = hook.memoizedState;863 if (prevState !== null) {864 if (nextDeps !== null) {865 const prevDeps: Array<mixed> | null = prevState[1];866 if (areHookInputsEqual(nextDeps, prevDeps)) {867 return prevState[0];868 }869 }870 }871 hook.memoizedState = [callback, nextDeps];872 return callback;873}874function mountMemo<T>(875 nextCreate: () => T,876 deps: Array<mixed> | void | null,877): T {878 const hook = mountWorkInProgressHook();879 const nextDeps = deps === undefined ? null : deps;880 const nextValue = nextCreate();881 hook.memoizedState = [nextValue, nextDeps];882 return nextValue;883}884function updateMemo<T>(885 nextCreate: () => T,886 deps: Array<mixed> | void | null,887): T {888 const hook = updateWorkInProgressHook();889 const nextDeps = deps === undefined ? null : deps;890 const prevState = hook.memoizedState;891 if (prevState !== null) {892 // Assume these are defined. If they're not, areHookInputsEqual will warn.893 if (nextDeps !== null) {894 const prevDeps: Array<mixed> | null = prevState[1];895 if (areHookInputsEqual(nextDeps, prevDeps)) {896 return prevState[0];897 }898 }899 }900 const nextValue = nextCreate();901 hook.memoizedState = [nextValue, nextDeps];902 return nextValue;903}904// in a test-like environment, we want to warn if dispatchAction()905// is called outside of a batchedUpdates/TestUtils.act(...) call.906let shouldWarnForUnbatchedSetState = false;907if (__DEV__) {908 // jest isn't a 'global', it's just exposed to tests via a wrapped function909 // further, this isn't a test file, so flow doesn't recognize the symbol. So...910 // $FlowExpectedError - because requirements don't give a damn about your type sigs.911 if ('undefined' !== typeof jest) {912 shouldWarnForUnbatchedSetState = true;913 }914}915function dispatchAction<S, A>(916 fiber: Fiber,917 queue: UpdateQueue<S, A>,918 action: A,919) {920 invariant(921 numberOfReRenders < RE_RENDER_LIMIT,922 'Too many re-renders. React limits the number of renders to prevent ' +923 'an infinite loop.',924 );925 if (__DEV__) {926 warning(927 arguments.length <= 3,928 "State updates from the useState() and useReducer() Hooks don't support the " +929 'second callback argument. To execute a side effect after ' +930 'rendering, declare it in the component body with useEffect().',931 );932 }933 const alternate = fiber.alternate;934 if (935 fiber === currentlyRenderingFiber ||936 (alternate !== null && alternate === currentlyRenderingFiber)937 ) {938 // This is a render phase update. Stash it in a lazily-created map of939 // queue -> linked list of updates. After this render pass, we'll restart940 // and apply the stashed updates on top of the work-in-progress hook.941 didScheduleRenderPhaseUpdate = true;942 const update: Update<S, A> = {943 expirationTime: renderExpirationTime,944 action,945 eagerReducer: null,946 eagerState: null,947 next: null,948 };949 if (renderPhaseUpdates === null) {950 renderPhaseUpdates = new Map();951 }952 const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);953 if (firstRenderPhaseUpdate === undefined) {954 renderPhaseUpdates.set(queue, update);955 } else {956 // Append the update to the end of the list.957 let lastRenderPhaseUpdate = firstRenderPhaseUpdate;958 while (lastRenderPhaseUpdate.next !== null) {959 lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;960 }961 lastRenderPhaseUpdate.next = update;962 }963 } else {964 flushPassiveEffects();965 const currentTime = requestCurrentTime();966 const expirationTime = computeExpirationForFiber(currentTime, fiber);967 const update: Update<S, A> = {968 expirationTime,969 action,970 eagerReducer: null,971 eagerState: null,972 next: null,973 };974 // Append the update to the end of the list.975 const last = queue.last;976 if (last === null) {977 // This is the first update. Create a circular list.978 update.next = update;979 } else {980 const first = last.next;981 if (first !== null) {982 // Still circular.983 update.next = first;984 }985 last.next = update;986 }987 queue.last = update;988 if (989 fiber.expirationTime === NoWork &&990 (alternate === null || alternate.expirationTime === NoWork)991 ) {992 // The queue is currently empty, which means we can eagerly compute the993 // next state before entering the render phase. If the new state is the994 // same as the current state, we may be able to bail out entirely.995 const lastRenderedReducer = queue.lastRenderedReducer;996 if (lastRenderedReducer !== null) {997 let prevDispatcher;998 if (__DEV__) {999 prevDispatcher = ReactCurrentDispatcher.current;1000 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1001 }1002 try {1003 const currentState: S = (queue.lastRenderedState: any);1004 const eagerState = lastRenderedReducer(currentState, action);1005 // Stash the eagerly computed state, and the reducer used to compute1006 // it, on the update object. If the reducer hasn't changed by the1007 // time we enter the render phase, then the eager state can be used1008 // without calling the reducer again.1009 update.eagerReducer = lastRenderedReducer;1010 update.eagerState = eagerState;1011 if (is(eagerState, currentState)) {1012 // Fast path. We can bail out without scheduling React to re-render.1013 // It's still possible that we'll need to rebase this update later,1014 // if the component re-renders for a different reason and by that1015 // time the reducer has changed.1016 return;1017 }1018 } catch (error) {1019 // Suppress the error. It will throw again in the render phase.1020 } finally {1021 if (__DEV__) {1022 ReactCurrentDispatcher.current = prevDispatcher;1023 }1024 }1025 }1026 }1027 if (__DEV__) {1028 if (shouldWarnForUnbatchedSetState === true) {1029 warnIfNotCurrentlyBatchingInDev(fiber);1030 }1031 }1032 scheduleWork(fiber, expirationTime);1033 }1034}1035export const ContextOnlyDispatcher: Dispatcher = {1036 readContext,1037 useCallback: throwInvalidHookError,1038 useContext: throwInvalidHookError,1039 useEffect: throwInvalidHookError,1040 useImperativeHandle: throwInvalidHookError,1041 useLayoutEffect: throwInvalidHookError,1042 useMemo: throwInvalidHookError,1043 useReducer: throwInvalidHookError,1044 useRef: throwInvalidHookError,1045 useState: throwInvalidHookError,1046 useDebugValue: throwInvalidHookError,1047};1048const HooksDispatcherOnMount: Dispatcher = {1049 readContext,1050 useCallback: mountCallback,1051 useContext: readContext,1052 useEffect: mountEffect,1053 useImperativeHandle: mountImperativeHandle,1054 useLayoutEffect: mountLayoutEffect,1055 useMemo: mountMemo,1056 useReducer: mountReducer,1057 useRef: mountRef,1058 useState: mountState,1059 useDebugValue: mountDebugValue,1060};1061const HooksDispatcherOnUpdate: Dispatcher = {1062 readContext,1063 useCallback: updateCallback,1064 useContext: readContext,1065 useEffect: updateEffect,1066 useImperativeHandle: updateImperativeHandle,1067 useLayoutEffect: updateLayoutEffect,1068 useMemo: updateMemo,1069 useReducer: updateReducer,1070 useRef: updateRef,1071 useState: updateState,1072 useDebugValue: updateDebugValue,1073};1074let HooksDispatcherOnMountInDEV: Dispatcher | null = null;1075let HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher | null = null;1076let HooksDispatcherOnUpdateInDEV: Dispatcher | null = null;1077let InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher | null = null;1078let InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher | null = null;1079if (__DEV__) {1080 const warnInvalidContextAccess = () => {1081 warning(1082 false,1083 'Context can only be read while React is rendering. ' +1084 'In classes, you can read it in the render method or getDerivedStateFromProps. ' +1085 'In function components, you can read it directly in the function body, but not ' +1086 'inside Hooks like useReducer() or useMemo().',1087 );1088 };1089 const warnInvalidHookAccess = () => {1090 warning(1091 false,1092 'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +1093 'You can only call Hooks at the top level of your React function. ' +1094 'For more information, see ' +1095 'https://fb.me/rules-of-hooks',1096 );1097 };1098 HooksDispatcherOnMountInDEV = {1099 readContext<T>(1100 context: ReactContext<T>,1101 observedBits: void | number | boolean,1102 ): T {1103 return readContext(context, observedBits);1104 },1105 useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {1106 currentHookNameInDev = 'useCallback';1107 mountHookTypesDev();1108 return mountCallback(callback, deps);1109 },1110 useContext<T>(1111 context: ReactContext<T>,1112 observedBits: void | number | boolean,1113 ): T {1114 currentHookNameInDev = 'useContext';1115 mountHookTypesDev();1116 return readContext(context, observedBits);1117 },1118 useEffect(1119 create: () => (() => void) | void,1120 deps: Array<mixed> | void | null,1121 ): void {1122 currentHookNameInDev = 'useEffect';1123 mountHookTypesDev();1124 return mountEffect(create, deps);1125 },1126 useImperativeHandle<T>(1127 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,1128 create: () => T,1129 deps: Array<mixed> | void | null,1130 ): void {1131 currentHookNameInDev = 'useImperativeHandle';1132 mountHookTypesDev();1133 return mountImperativeHandle(ref, create, deps);1134 },1135 useLayoutEffect(1136 create: () => (() => void) | void,1137 deps: Array<mixed> | void | null,1138 ): void {1139 currentHookNameInDev = 'useLayoutEffect';1140 mountHookTypesDev();1141 return mountLayoutEffect(create, deps);1142 },1143 useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {1144 currentHookNameInDev = 'useMemo';1145 mountHookTypesDev();1146 const prevDispatcher = ReactCurrentDispatcher.current;1147 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1148 try {1149 return mountMemo(create, deps);1150 } finally {1151 ReactCurrentDispatcher.current = prevDispatcher;1152 }1153 },1154 useReducer<S, I, A>(1155 reducer: (S, A) => S,1156 initialArg: I,1157 init?: I => S,1158 ): [S, Dispatch<A>] {1159 currentHookNameInDev = 'useReducer';1160 mountHookTypesDev();1161 const prevDispatcher = ReactCurrentDispatcher.current;1162 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1163 try {1164 return mountReducer(reducer, initialArg, init);1165 } finally {1166 ReactCurrentDispatcher.current = prevDispatcher;1167 }1168 },1169 useRef<T>(initialValue: T): {current: T} {1170 currentHookNameInDev = 'useRef';1171 mountHookTypesDev();1172 return mountRef(initialValue);1173 },1174 useState<S>(1175 initialState: (() => S) | S,1176 ): [S, Dispatch<BasicStateAction<S>>] {1177 currentHookNameInDev = 'useState';1178 mountHookTypesDev();1179 const prevDispatcher = ReactCurrentDispatcher.current;1180 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1181 try {1182 return mountState(initialState);1183 } finally {1184 ReactCurrentDispatcher.current = prevDispatcher;1185 }1186 },1187 useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {1188 currentHookNameInDev = 'useDebugValue';1189 mountHookTypesDev();1190 return mountDebugValue(value, formatterFn);1191 },1192 };1193 HooksDispatcherOnMountWithHookTypesInDEV = {1194 readContext<T>(1195 context: ReactContext<T>,1196 observedBits: void | number | boolean,1197 ): T {1198 return readContext(context, observedBits);1199 },1200 useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {1201 currentHookNameInDev = 'useCallback';1202 updateHookTypesDev();1203 return mountCallback(callback, deps);1204 },1205 useContext<T>(1206 context: ReactContext<T>,1207 observedBits: void | number | boolean,1208 ): T {1209 currentHookNameInDev = 'useContext';1210 updateHookTypesDev();1211 return readContext(context, observedBits);1212 },1213 useEffect(1214 create: () => (() => void) | void,1215 deps: Array<mixed> | void | null,1216 ): void {1217 currentHookNameInDev = 'useEffect';1218 updateHookTypesDev();1219 return mountEffect(create, deps);1220 },1221 useImperativeHandle<T>(1222 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,1223 create: () => T,1224 deps: Array<mixed> | void | null,1225 ): void {1226 currentHookNameInDev = 'useImperativeHandle';1227 updateHookTypesDev();1228 return mountImperativeHandle(ref, create, deps);1229 },1230 useLayoutEffect(1231 create: () => (() => void) | void,1232 deps: Array<mixed> | void | null,1233 ): void {1234 currentHookNameInDev = 'useLayoutEffect';1235 updateHookTypesDev();1236 return mountLayoutEffect(create, deps);1237 },1238 useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {1239 currentHookNameInDev = 'useMemo';1240 updateHookTypesDev();1241 const prevDispatcher = ReactCurrentDispatcher.current;1242 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1243 try {1244 return mountMemo(create, deps);1245 } finally {1246 ReactCurrentDispatcher.current = prevDispatcher;1247 }1248 },1249 useReducer<S, I, A>(1250 reducer: (S, A) => S,1251 initialArg: I,1252 init?: I => S,1253 ): [S, Dispatch<A>] {1254 currentHookNameInDev = 'useReducer';1255 updateHookTypesDev();1256 const prevDispatcher = ReactCurrentDispatcher.current;1257 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1258 try {1259 return mountReducer(reducer, initialArg, init);1260 } finally {1261 ReactCurrentDispatcher.current = prevDispatcher;1262 }1263 },1264 useRef<T>(initialValue: T): {current: T} {1265 currentHookNameInDev = 'useRef';1266 updateHookTypesDev();1267 return mountRef(initialValue);1268 },1269 useState<S>(1270 initialState: (() => S) | S,1271 ): [S, Dispatch<BasicStateAction<S>>] {1272 currentHookNameInDev = 'useState';1273 updateHookTypesDev();1274 const prevDispatcher = ReactCurrentDispatcher.current;1275 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1276 try {1277 return mountState(initialState);1278 } finally {1279 ReactCurrentDispatcher.current = prevDispatcher;1280 }1281 },1282 useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {1283 currentHookNameInDev = 'useDebugValue';1284 updateHookTypesDev();1285 return mountDebugValue(value, formatterFn);1286 },1287 };1288 HooksDispatcherOnUpdateInDEV = {1289 readContext<T>(1290 context: ReactContext<T>,1291 observedBits: void | number | boolean,1292 ): T {1293 return readContext(context, observedBits);1294 },1295 useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {1296 currentHookNameInDev = 'useCallback';1297 updateHookTypesDev();1298 return updateCallback(callback, deps);1299 },1300 useContext<T>(1301 context: ReactContext<T>,1302 observedBits: void | number | boolean,1303 ): T {1304 currentHookNameInDev = 'useContext';1305 updateHookTypesDev();1306 return readContext(context, observedBits);1307 },1308 useEffect(1309 create: () => (() => void) | void,1310 deps: Array<mixed> | void | null,1311 ): void {1312 currentHookNameInDev = 'useEffect';1313 updateHookTypesDev();1314 return updateEffect(create, deps);1315 },1316 useImperativeHandle<T>(1317 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,1318 create: () => T,1319 deps: Array<mixed> | void | null,1320 ): void {1321 currentHookNameInDev = 'useImperativeHandle';1322 updateHookTypesDev();1323 return updateImperativeHandle(ref, create, deps);1324 },1325 useLayoutEffect(1326 create: () => (() => void) | void,1327 deps: Array<mixed> | void | null,1328 ): void {1329 currentHookNameInDev = 'useLayoutEffect';1330 updateHookTypesDev();1331 return updateLayoutEffect(create, deps);1332 },1333 useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {1334 currentHookNameInDev = 'useMemo';1335 updateHookTypesDev();1336 const prevDispatcher = ReactCurrentDispatcher.current;1337 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1338 try {1339 return updateMemo(create, deps);1340 } finally {1341 ReactCurrentDispatcher.current = prevDispatcher;1342 }1343 },1344 useReducer<S, I, A>(1345 reducer: (S, A) => S,1346 initialArg: I,1347 init?: I => S,1348 ): [S, Dispatch<A>] {1349 currentHookNameInDev = 'useReducer';1350 updateHookTypesDev();1351 const prevDispatcher = ReactCurrentDispatcher.current;1352 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1353 try {1354 return updateReducer(reducer, initialArg, init);1355 } finally {1356 ReactCurrentDispatcher.current = prevDispatcher;1357 }1358 },1359 useRef<T>(initialValue: T): {current: T} {1360 currentHookNameInDev = 'useRef';1361 updateHookTypesDev();1362 return updateRef(initialValue);1363 },1364 useState<S>(1365 initialState: (() => S) | S,1366 ): [S, Dispatch<BasicStateAction<S>>] {1367 currentHookNameInDev = 'useState';1368 updateHookTypesDev();1369 const prevDispatcher = ReactCurrentDispatcher.current;1370 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1371 try {1372 return updateState(initialState);1373 } finally {1374 ReactCurrentDispatcher.current = prevDispatcher;1375 }1376 },1377 useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {1378 currentHookNameInDev = 'useDebugValue';1379 updateHookTypesDev();1380 return updateDebugValue(value, formatterFn);1381 },1382 };1383 InvalidNestedHooksDispatcherOnMountInDEV = {1384 readContext<T>(1385 context: ReactContext<T>,1386 observedBits: void | number | boolean,1387 ): T {1388 warnInvalidContextAccess();1389 return readContext(context, observedBits);1390 },1391 useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {1392 currentHookNameInDev = 'useCallback';1393 warnInvalidHookAccess();1394 mountHookTypesDev();1395 return mountCallback(callback, deps);1396 },1397 useContext<T>(1398 context: ReactContext<T>,1399 observedBits: void | number | boolean,1400 ): T {1401 currentHookNameInDev = 'useContext';1402 warnInvalidHookAccess();1403 mountHookTypesDev();1404 return readContext(context, observedBits);1405 },1406 useEffect(1407 create: () => (() => void) | void,1408 deps: Array<mixed> | void | null,1409 ): void {1410 currentHookNameInDev = 'useEffect';1411 warnInvalidHookAccess();1412 mountHookTypesDev();1413 return mountEffect(create, deps);1414 },1415 useImperativeHandle<T>(1416 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,1417 create: () => T,1418 deps: Array<mixed> | void | null,1419 ): void {1420 currentHookNameInDev = 'useImperativeHandle';1421 warnInvalidHookAccess();1422 mountHookTypesDev();1423 return mountImperativeHandle(ref, create, deps);1424 },1425 useLayoutEffect(1426 create: () => (() => void) | void,1427 deps: Array<mixed> | void | null,1428 ): void {1429 currentHookNameInDev = 'useLayoutEffect';1430 warnInvalidHookAccess();1431 mountHookTypesDev();1432 return mountLayoutEffect(create, deps);1433 },1434 useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {1435 currentHookNameInDev = 'useMemo';1436 warnInvalidHookAccess();1437 mountHookTypesDev();1438 const prevDispatcher = ReactCurrentDispatcher.current;1439 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1440 try {1441 return mountMemo(create, deps);1442 } finally {1443 ReactCurrentDispatcher.current = prevDispatcher;1444 }1445 },1446 useReducer<S, I, A>(...
learn-react-hook.js
Source:learn-react-hook.js
1// 以setState为ä¾åæreact-hookæºç ç¥è¯2// è¿éuseStateå
¶å®æ¯dispatcher对象éé¢çä¸ä¸ªæ¹æ³3export function useState < S > (initialState: (() => S) | S) {4 const dispatcher = resolveDispatcher();5 return dispatcher.useState(initialState);6}7// 继ç»è·è¸ªdispatcherå³resolveDispatcher()çè¿åå¼8function resolveDispatcher() {9 //主è¦è¿æ¯ä½¿ç¨çReactCurrentDispatcherè¿ä¸ªå¯¹è±¡çå¼10 const dispatcher = ReactCurrentDispatcher.current;11 //...12 return dispatcher;13}14// 继ç»è·ä¸ReactCurrentDispatcher15const ReactCurrentDispatcher = {16 /**17 * @internal18 * @type {ReactComponent}19 */20 // 追寻å°å
¶å®æå使ç¨çè¿æ¯reactèªèº«æä¾çDispatcher,æç»æåçè¿æ¯æ°çåè°å¨ä¸çFiberHooks21 // import type {Dispatcher} from 'react-reconciler/src/ReactFiberHooks';22 current: (null: null | Dispatcher),23};24// 继ç»è·è¿Dispatcher path: 'react-reconciler/src/ReactFiberHooks'25// è¿å
¥Dispatcher åç°Dispatcherççå½éé¢ä¸å¤§å ç¸å
³çhook,å
¨é¨é½å¨è¿éå®ä¹å¥½äºï¼æ¾å°useStateç声æ26export type Dispatcher = {27 readContext<T>(28 context: ReactContext<T>,29 observedBits: void | number | boolean,30 ): T,31 // useStateå®ä¹çæ ¼å¼ï¼ä¸ä¸ªè¿å
¥çæ³åSæ¯å½æ°æè
ä¸ä¸ªå¼ï¼åæ¶è¿åä¸ä¸ªS以åå¨ä½ç¨äºæ´æ°S32 useState<S>(initialState: (() => S) | S): [S, Dispatch<BasicStateAction<S>>],33 useReducer<S, I, A>(34 reducer: (S, A) => S,35 initialArg: I,36 init?: (I) => S,37 ): [S, Dispatch<A>],38 useContext<T>(39 context: ReactContext<T>,40 observedBits: void | number | boolean,41 ): T,42 useRef<T>(initialValue: T): {current: T},43 useEffect(44 create: () => (() => void) | void,45 deps: Array<mixed> | void | null,46 ): void,47 useLayoutEffect(48 create: () => (() => void) | void,49 deps: Array<mixed> | void | null,50 ): void,51 useCallback<T>(callback: T, deps: Array<mixed> | void | null): T,52 useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T,53 useImperativeHandle<T>(54 ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,55 create: () => T,56 deps: Array<mixed> | void | null,57 ): void,58 useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,59};60// è·è¿Dispatcherçæ£çé»è¾å®ä½,åç°æåç§åæ ·çå®ä½ä½¿ç¨å°äºDispatcherçå®ä¹å¨æ¤éæ©hookæ载以åhookæ´æ°çç¶æå®ä½å»åæ61//Hooks æè½½å¨ç»ä»¶æ¶çæ
å½¢, å
¨é½æ¯mountç¶æ62const HooksDispatcherOnMount: Dispatcher = {63 readContext,64 useCallback: mountCallback,65 useContext: readContext,66 useEffect: mountEffect,67 useImperativeHandle: mountImperativeHandle,68 useLayoutEffect: mountLayoutEffect,69 useMemo: mountMemo,70 useReducer: mountReducer,71 useRef: mountRef,72 //useStateå¨mountç¶æçæ¶å对åºçmountStateè¿è¡è·è¸ª73 useState: mountState,74 useDebugValue: mountDebugValue,75};76// mountState ç¸å
³ç代ç 77function mountState<S>(78 initialState: (() => S) | S,79): [S, Dispatch<BasicStateAction<S>>] {80 // å®ä¹ä¸ä¸ªhookçä¸è¥¿ï¼è¿ä¸ªhookä¸ç¥éæ¯ä¸ªä»ä¹ä¸è¥¿ï¼å¥½åæ¯ä»workInProgressè¿ä¸ªFiberæ éé¢æ¿åºæ¥çä¸è¥¿81 const hook = mountWorkInProgressHook();82 if (typeof initialState === 'function') {83 // æ°æ§åå§ååå§ç¶æ84 initialState = initialState();85 }86 // å½åhookè®°ä½çç¶æmomoizedState = initialStateå³åå§åstateçå¼87 hook.memoizedState = hook.baseState = initialState;88 // å®ä¹ä¸ä¸ªhookçéå89 const queue = (hook.queue = {90 last: null, // ä¸æç½æ¯ä»ä¹ä¸è¥¿91 dispatch: null, // è¿ä¸ªæè§æç¹åç¶æ管ççå¨ä½è§¦åå¨92 lastRenderedReducer: basicStateReducer, //ä¸ç¥éä»ä¹ä¸è¥¿ï¼æ ¹æ®å½åï¼å¯ä»¥è®¤ä¸ºæ¯ä¸ä¸æ¬¡æ¸²æçrenducer93 lastRenderedState: (initialState: any), // è¿ä¸ªåºè¯¥æ¯ä¸ä¸æ¬¡æ¸²æçstateå¦94 });95 const dispatch: Dispatch<96 BasicStateAction<S>,97 > = (queue.dispatch = (dispatchAction.bind(98 null,99 // Flow doesn't know this is non-null, but we do.100 ((currentlyRenderingFiber: any): Fiber),101 queue,102 ): any)); // è¿éhook.queue.dispatchå
¶å®å°±æ¯reactéé¢å
ç½®çä¸ä¸ªdispatchActionçå½æ°ï¼å
·ä½éé¢ä¼°è®¡æ¯å¹²åçä¸å¤ªæ¸
æ¥ï¼ç¨ååæ103 return [hook.memoizedState, dispatch];104}105/**106 * è¿éåæ以ä¸çmountStateåå æ¥è¿è¡107 * 1ãmountWorkInProgressHookè¿ä¸ªå½æ°éé¢è¿åçæ¯ä»ä¹ä¸è¥¿ï¼éé¢æä»ä¹ä¸è¥¿ï¼ä¸ºä»ä¹å½å为hook?108 * 2ãdispatchActionå½æ°109 * 3ãæ¤æ¥å¯ä¸ç¨è¿ä¹è¯¦ç»è¿è¡åæï¼basicStateReduceræ¯ä»ä¹ï¼å®æä»ä¹ç¨ï¼æä¹ç¨ï¼ä»¥åcurrentlyRenderingFiberæ¯ä¸ªä»ä¹ä¸è¥¿110 */111 // 1ãmountWorkInProgressHookæ¯ä¸ªä»ä¹ä¸è¥¿112 function mountWorkInProgressHook(): Hook {113 // å
¶å®å°±æ¯è¿åä¸ä¸ªhookï¼å°±æ¯ä¸ä¸ªç®åç对象114 const hook: Hook = {115 memoizedState: null,116 baseState: null,117 queue: null,118 baseUpdate: null,119 next: null,120 };121 // è¿éå
¶å®å°±æ¯æ建ä¸ä¸ªç±»ä¼¼é¾è¡¨çä¸è¥¿ï¼122 // HookA -> HookB -> HookC -> HookD ?123 // æè§å°±æ¯è¿ä¸ªä¸è¥¿äºæåæå½åé¾è¡¨èç¹è¿å124 if (workInProgressHook === null) {125 // This is the first hook in the list126 // è¿ä¸ªfirstWorkInprogressHookä¼¼ä¹æ¯å
¨å±åé127 firstWorkInProgressHook = workInProgressHook = hook;128 } else {129 // Append to the end of the list130 workInProgressHook = workInProgressHook.next = hook;131 }132 return workInProgressHook;133}134// 2ãæç½äºhookæ¯ä¸ªä»ä¹ä¸è¥¿ï¼ç°å¨ç¬¬äºæ¥ï¼dispatcherActionæ¯ä¸ªä»ä¹ä¸è¥¿?135// è¿ä¸ªä¸è¥¿æ¯è¾é¾åçèµ·æ¥å°±æºå¤æçï¼ä½æ¯ç°å¨å±ä»¬å
ä¸å»å¨å®ï¼å 为å±ä»¬åªæ¯è¿è¡çä¸ä¸ªæè½½å¨ä½ï¼æ²¡æä»»ä½å¨ä½è¡ä¸ºï¼æ æ³è§¦å该å½æ°æ§è¡136function dispatchAction<S, A>(137 fiber: Fiber, // currentlyRenderingFiber138 queue: UpdateQueue<S, A>, // mounté¶æ®µqueue {last: null, lastRenderedReducer: basicStateReducer, lastRenderedState: (initialState: any)}139 action: A, // mounté¶æ®µ action 为undefined140) {141 invariant(142 numberOfReRenders < RE_RENDER_LIMIT,143 'Too many re-renders. React limits the number of renders to prevent ' +144 'an infinite loop.',145 );146 if (__DEV__) {147 warning(148 arguments.length <= 3,149 "State updates from the useState() and useReducer() Hooks don't support the " +150 'second callback argument. To execute a side effect after ' +151 'rendering, declare it in the component body with useEffect().',152 );153 }154 const alternate = fiber.alternate;155 if (156 fiber === currentlyRenderingFiber ||157 (alternate !== null && alternate === currentlyRenderingFiber)158 ) {159 // This is a render phase update. Stash it in a lazily-created map of160 // queue -> linked list of updates. After this render pass, we'll restart161 // and apply the stashed updates on top of the work-in-progress hook.162 didScheduleRenderPhaseUpdate = true;163 const update: Update<S, A> = {164 expirationTime: renderExpirationTime,165 action,166 eagerReducer: null,167 eagerState: null,168 next: null,169 };170 if (renderPhaseUpdates === null) {171 renderPhaseUpdates = new Map();172 }173 const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);174 if (firstRenderPhaseUpdate === undefined) {175 renderPhaseUpdates.set(queue, update);176 } else {177 // Append the update to the end of the list.178 let lastRenderPhaseUpdate = firstRenderPhaseUpdate;179 while (lastRenderPhaseUpdate.next !== null) {180 lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;181 }182 lastRenderPhaseUpdate.next = update;183 }184 } else {185 flushPassiveEffects();186 const currentTime = requestCurrentTime();187 const expirationTime = computeExpirationForFiber(currentTime, fiber);188 const update: Update<S, A> = {189 expirationTime,190 action,191 eagerReducer: null,192 eagerState: null,193 next: null,194 };195 // Append the update to the end of the list.196 const last = queue.last;197 if (last === null) {198 // This is the first update. Create a circular list.199 update.next = update;200 } else {201 const first = last.next;202 if (first !== null) {203 // Still circular.204 update.next = first;205 }206 last.next = update;207 }208 queue.last = update;209 if (210 fiber.expirationTime === NoWork &&211 (alternate === null || alternate.expirationTime === NoWork)212 ) {213 // The queue is currently empty, which means we can eagerly compute the214 // next state before entering the render phase. If the new state is the215 // same as the current state, we may be able to bail out entirely.216 const lastRenderedReducer = queue.lastRenderedReducer;217 if (lastRenderedReducer !== null) {218 let prevDispatcher;219 if (__DEV__) {220 prevDispatcher = ReactCurrentDispatcher.current;221 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;222 }223 try {224 const currentState: S = (queue.lastRenderedState: any);225 const eagerState = lastRenderedReducer(currentState, action);226 // Stash the eagerly computed state, and the reducer used to compute227 // it, on the update object. If the reducer hasn't changed by the228 // time we enter the render phase, then the eager state can be used229 // without calling the reducer again.230 update.eagerReducer = lastRenderedReducer;231 update.eagerState = eagerState;232 if (is(eagerState, currentState)) {233 // Fast path. We can bail out without scheduling React to re-render.234 // It's still possible that we'll need to rebase this update later,235 // if the component re-renders for a different reason and by that236 // time the reducer has changed.237 return;238 }239 } catch (error) {240 // Suppress the error. It will throw again in the render phase.241 } finally {242 if (__DEV__) {243 ReactCurrentDispatcher.current = prevDispatcher;244 }245 }246 }247 }248 if (__DEV__) {249 // jest isn't a 'global', it's just exposed to tests via a wrapped function250 // further, this isn't a test file, so flow doesn't recognize the symbol. So...251 // $FlowExpectedError - because requirements don't give a damn about your type sigs.252 if ('undefined' !== typeof jest) {253 warnIfNotCurrentlyActingUpdatesInDev(fiber);254 }255 }256 scheduleWork(fiber, expirationTime);257 }258}259// 第ä¸æ¥ï¼ææ 260// ç°å¨ç¸å½äºåå§å好äºsetStateçhookå°±å¦åæ§è¡äºä¸æ¬¡ä¸é¢ç代ç 261const [name, setName] = useState('initialName');...
Using AI Code Generation
1const { mountLayoutEffect } = require('playwright');2const { chromium } = require('playwright');3const browser = await chromium.launch();4const page = await browser.newPage();5await mountLayoutEffect(page);6const { layoutEffect } = require('playwright');7await layoutEffect(page, () => {8 const { contentSize, visualViewport } = page.layout();9 console.log(contentSize);10 console.log(visualViewport);11});12layoutEffect(page, callback[, options])13{ width: number, height: number }14{ x: number, y: number, width: number, height: number }15const { layoutEffect } = require('playwright');16await layoutEffect(page, () => {17 const { contentSize, visualViewport } = page.layout();18 console.log(contentSize);19 console.log(visualViewport);20});21const { layoutEffect } = require('playwright');22const { chromium } = require('playwright');23const browser = await chromium.launch();24const page = await browser.newPage();25await layoutEffect(page, () => {26 const { contentSize, visualViewport } = page.layout();27 console.log(contentSize);28 console.log(visualViewport);29});30{ width: 1920, height: 1080 }31{ x: 0, y: 0, width: 1920, height: 1053 }32mountLayoutEffect(page)
Using AI Code Generation
1const { mountLayoutEffect } = require('@playwright/test');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4 await mountLayoutEffect(page, () => {5 });6});7const { mountLayoutEffect } = require('@playwright/test');8const { test } = require('@playwright/test');9test.describe('test', () => {10 test.beforeEach(async ({ page }) => {11 await mountLayoutEffect(page, () => {12 });13 });14 test('test', async () => {15 });16});17const { mountLayoutEffect } = require('@playwright/test');18const { test } = require('@playwright/test');19test.describe('test', () => {20 test.beforeEach(async ({ page }) => {21 await mountLayoutEffect(page, () => {22 });23 });24 test('test', async () => {25 });26});27const { mountLayoutEffect } = require('@playwright/test');28const { test } = require('@playwright/test');29test.describe('test', () => {30 test.beforeEach(async ({ page }) => {31 await mountLayoutEffect(page, () => {32 });33 });34 test('test', async () => {35 });36});
Using AI Code Generation
1const { mountLayoutEffect } = require("playwright-core/lib/server/page");2mountLayoutEffect();3const { chromium } = require("playwright-core");4(async () => {5 const browser = await chromium.launch();6 const context = await browser.newContext();7 const page = await context.newPage();8 await page.screenshot({ path: "screenshot.png" });9 await browser.close();10})();
Using AI Code Generation
1const { mountLayoutEffect } = require('@playwright/test/lib/server/supplements/recorder/recorderSupplement');2const { Page } = require('@playwright/test/lib/server/page');3const { ElementHandle } = require('@playwright/test/lib/server/dom');4const { Frame } = require('@playwright/test/lib/server/frames');5const { mountLayoutEffect } = require('@playwright/test/lib/server/supplements/recorder/recorderSupplement');6const { Page } = require('@playwright/test/lib/server/page');7const { ElementHandle } = require('@playwright/test/lib/server/dom');8const { Frame } = require('@playwright/test/lib/server/frames');9const { mountLayoutEffect } = require('@playwright/test/lib/server/supplements/recorder/recorderSupplement');10const { Page } = require('@playwright/test/lib/server/page');11const { ElementHandle } = require('@playwright/test/lib/server/dom');12const { Frame } = require('@playwright/test/lib/server/frames');13const { mountLayoutEffect } = require('@playwright/test/lib/server/supplements/recorder/recorderSupplement');14const { Page } = require('@playwright/test/lib/server/page');15const { ElementHandle } = require('@playwright/test/lib/server/dom');16const { Frame } = require('@playwright/test/lib/server/frames');17const { mountLayoutEffect } = require('@playwright/test/lib/server/supplements/recorder/recorderSupplement');18const { Page } = require('@playwright/test/lib/server/page');19const { ElementHandle } = require('@playwright/test/lib/server/dom');20const { Frame } = require('@playwright/test/lib/server/frames');21const { mountLayoutEffect } = require('@playwright/test/lib/server/supplements/recorder/recorderSupplement');22const { Page } = require('@playwright/test/lib/server/page');23const { ElementHandle } = require('@playwright/test/lib/server/dom');24const { Frame } = require('@playwright/test/lib/server/frames');
Using AI Code Generation
1const { mountLayoutEffect } = require('@playwright/test');2const { Page } = require('@playwright/test/lib/server/page');3const { ElementHandle } = require('@playwright/test/lib/server/dom');4const { mountLayoutEffect } = require('@playwright/test');5const { Page } = require('@playwright/test/lib/server/page');6const { ElementHandle } = require('@playwright/test/lib/server/dom');7const { mountLayoutEffect } = require('@playwright/test');8const { Page } = require('@playwright/test/lib/server/page');9const { ElementHandle } = require('@playwright/test/lib/server/dom');10const { mountLayoutEffect } = require('@playwright/test');11const { Page } = require('@playwright/test/lib/server/page');12const { ElementHandle } = require('@playwright/test/lib/server/dom');13const { mountLayoutEffect } = require('@playwright/test');14const { Page } = require('@playwright/test/lib/server/page');15const { ElementHandle } = require('@playwright/test/lib/server/dom');16const { mountLayoutEffect } = require('@playwright/test');17const { Page } = require('@playwright/test/lib/server/page');18const { ElementHandle } = require('@playwright/test/lib/server/dom');19const { mountLayoutEffect } = require('@playwright/test');20const { Page } = require('@playwright/test/lib/server/page');21const { ElementHandle } = require('@playwright/test/lib/server/dom');22const { mountLayoutEffect } = require('@playwright/test');23const { Page } = require('@playwright/test/lib/server/page');24const { ElementHandle } = require('@playwright/test/lib/server/dom');25const { mountLayoutEffect } = require('@playwright/test');26const { Page } = require('@playwright/test/lib/server/page');27const { ElementHandle } = require('@playwright/test/lib/server/dom');
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.waitForLoadState('domcontentloaded');7 const element = await page.$('h1');8 await page.evaluate(element => {9 return new Promise(resolve => {10 const observer = new MutationObserver(resolve);11 observer.observe(element, { attributes: true });12 });13 }, element);14 await page.waitForLoadState('networkidle');15 await browser.close();16})();17const { chromium } = require('playwright');18describe('My Test', () => {19 it('should work', async () => {20 const browser = await chromium.launch();21 const context = await browser.newContext();22 const page = await context.newPage();23 await page.waitForLoadState('domcontentloaded');24 const element = await page.$('h1');25 await page.evaluate(element => {26 return new Promise(resolve => {27 const observer = new MutationObserver(resolve);28 observer.observe(element, { attributes: true });29 });30 }, element);31 await page.waitForLoadState('networkidle');32 await browser.close();33 });34});35import { chromium } from 'playwright';36(async () => {37 const browser = await chromium.launch();38 const context = await browser.newContext();39 const page = await context.newPage();40 await page.waitForLoadState('domcontentloaded');41 const element = await page.$('h1');42 await page.evaluate(element => {43 return new Promise(resolve => {44 const observer = new MutationObserver(resolve);45 observer.observe(element, { attributes: true });46 });47 }, element);48 await page.waitForLoadState('networkidle');49 await browser.close();50})();
Using AI Code Generation
1import { mountLayoutEffect } from 'playwright-core/lib/server/dom.js';2export const test = async (page) => {3 await page.setContent(`<div id="container"><div id="child"></div></div>`);4 await page.evaluate((page) => {5 const container = document.querySelector('#container');6 const child = document.querySelector('#child');7 const effect = () => {8 const containerRect = container.getBoundingClientRect();9 const childRect = child.getBoundingClientRect();10 if (11 ) {12 console.log('effect');13 }14 };15 mountLayoutEffect(effect, []);16 });17};18module.exports = {19 {20 },21};22{23 "scripts": {24 },25 "devDependencies": {26 }27}
Using AI Code Generation
1const { mountLayoutEffect } = require('@playwright/test/lib/server/page');2await mountLayoutEffect();3await page.waitForSelector('.my-element');4const { test } = require('@playwright/test');5test('My Test', async ({ page }) => {6 await page.waitForSelector('.my-element');7 await page.waitForSelector('.my-other-element');8});
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!