How to use rerenderOpaqueIdentifier method in Playwright Internal

Best JavaScript code snippet using playwright-internal

ReactFiberHooks.new.js

Source:ReactFiberHooks.new.js Github

copy

Full Screen

...1489function updateOpaqueIdentifier() {1490 const id = updateState(undefined)[0];1491 return id;1492}1493function rerenderOpaqueIdentifier() {1494 const id = rerenderState(undefined)[0];1495 return id;1496}1497function dispatchAction (1498 fiber ,1499 queue ,1500 action ,1501) {1502 if (__DEV__) {1503 if (typeof arguments[3] === 'function') {1504 console.error(1505 "State updates from the useState() and useReducer() Hooks don't support the " +1506 'second callback argument. To execute a side effect after ' +1507 'rendering, declare it in the component body with useEffect().',1508 );1509 }1510 }1511 const eventTime = requestEventTime();1512 const lane = requestUpdateLane(fiber);1513 const update = {1514 lane,1515 action,1516 eagerReducer: null,1517 eagerState: null,1518 next: (null ),1519 };1520 // Append the update to the end of the list.1521 const pending = queue.pending;1522 if (pending === null) {1523 // This is the first update. Create a circular list.1524 update.next = update;1525 } else {1526 update.next = pending.next;1527 pending.next = update;1528 }1529 queue.pending = update;1530 const alternate = fiber.alternate;1531 if (1532 fiber === currentlyRenderingFiber ||1533 (alternate !== null && alternate === currentlyRenderingFiber)1534 ) {1535 // This is a render phase update. Stash it in a lazily-created map of1536 // queue -> linked list of updates. After this render pass, we'll restart1537 // and apply the stashed updates on top of the work-in-progress hook.1538 didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;1539 } else {1540 if (1541 fiber.lanes === NoLanes &&1542 (alternate === null || alternate.lanes === NoLanes)1543 ) {1544 // The queue is currently empty, which means we can eagerly compute the1545 // next state before entering the render phase. If the new state is the1546 // same as the current state, we may be able to bail out entirely.1547 const lastRenderedReducer = queue.lastRenderedReducer;1548 if (lastRenderedReducer !== null) {1549 let prevDispatcher;1550 if (__DEV__) {1551 prevDispatcher = ReactCurrentDispatcher.current;1552 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1553 }1554 try {1555 const currentState = (queue.lastRenderedState );1556 const eagerState = lastRenderedReducer(currentState, action);1557 // Stash the eagerly computed state, and the reducer used to compute1558 // it, on the update object. If the reducer hasn't changed by the1559 // time we enter the render phase, then the eager state can be used1560 // without calling the reducer again.1561 update.eagerReducer = lastRenderedReducer;1562 update.eagerState = eagerState;1563 if (is(eagerState, currentState)) {1564 // Fast path. We can bail out without scheduling React to re-render.1565 // It's still possible that we'll need to rebase this update later,1566 // if the component re-renders for a different reason and by that1567 // time the reducer has changed.1568 return;1569 }1570 } catch (error) {1571 // Suppress the error. It will throw again in the render phase.1572 } finally {1573 if (__DEV__) {1574 ReactCurrentDispatcher.current = prevDispatcher;1575 }1576 }1577 }1578 }1579 if (__DEV__) {1580 // $FlowExpectedError - jest isn't a global, and isn't recognized outside of tests1581 if (typeof jest !== 'undefined') {1582 warnIfNotScopedWithMatchingAct(fiber);1583 warnIfNotCurrentlyActingUpdatesInDev(fiber);1584 }1585 }1586 scheduleUpdateOnFiber(fiber, lane, eventTime);1587 }1588 if (__DEV__) {1589 if (enableDebugTracing) {1590 if (fiber.mode & DebugTracingMode) {1591 const name = getComponentName(fiber.type) || 'Unknown';1592 logStateUpdateScheduled(name, lane, action);1593 }1594 }1595 }1596 if (enableSchedulingProfiler) {1597 markStateUpdateScheduled(fiber, lane);1598 }1599}1600export const ContextOnlyDispatcher = {1601 readContext,1602 useCallback: throwInvalidHookError,1603 useContext: throwInvalidHookError,1604 useEffect: throwInvalidHookError,1605 useImperativeHandle: throwInvalidHookError,1606 useLayoutEffect: throwInvalidHookError,1607 useMemo: throwInvalidHookError,1608 useReducer: throwInvalidHookError,1609 useRef: throwInvalidHookError,1610 useState: throwInvalidHookError,1611 useDebugValue: throwInvalidHookError,1612 useDeferredValue: throwInvalidHookError,1613 useTransition: throwInvalidHookError,1614 useMutableSource: throwInvalidHookError,1615 useOpaqueIdentifier: throwInvalidHookError,1616 unstable_isNewReconciler: enableNewReconciler,1617};1618const HooksDispatcherOnMount = {1619 readContext,1620 useCallback: mountCallback,1621 useContext: readContext,1622 useEffect: mountEffect,1623 useImperativeHandle: mountImperativeHandle,1624 useLayoutEffect: mountLayoutEffect,1625 useMemo: mountMemo,1626 useReducer: mountReducer,1627 useRef: mountRef,1628 useState: mountState,1629 useDebugValue: mountDebugValue,1630 useDeferredValue: mountDeferredValue,1631 useTransition: mountTransition,1632 useMutableSource: mountMutableSource,1633 useOpaqueIdentifier: mountOpaqueIdentifier,1634 unstable_isNewReconciler: enableNewReconciler,1635};1636const HooksDispatcherOnUpdate = {1637 readContext,1638 useCallback: updateCallback,1639 useContext: readContext,1640 useEffect: updateEffect,1641 useImperativeHandle: updateImperativeHandle,1642 useLayoutEffect: updateLayoutEffect,1643 useMemo: updateMemo,1644 useReducer: updateReducer,1645 useRef: updateRef,1646 useState: updateState,1647 useDebugValue: updateDebugValue,1648 useDeferredValue: updateDeferredValue,1649 useTransition: updateTransition,1650 useMutableSource: updateMutableSource,1651 useOpaqueIdentifier: updateOpaqueIdentifier,1652 unstable_isNewReconciler: enableNewReconciler,1653};1654const HooksDispatcherOnRerender = {1655 readContext,1656 useCallback: updateCallback,1657 useContext: readContext,1658 useEffect: updateEffect,1659 useImperativeHandle: updateImperativeHandle,1660 useLayoutEffect: updateLayoutEffect,1661 useMemo: updateMemo,1662 useReducer: rerenderReducer,1663 useRef: updateRef,1664 useState: rerenderState,1665 useDebugValue: updateDebugValue,1666 useDeferredValue: rerenderDeferredValue,1667 useTransition: rerenderTransition,1668 useMutableSource: updateMutableSource,1669 useOpaqueIdentifier: rerenderOpaqueIdentifier,1670 unstable_isNewReconciler: enableNewReconciler,1671};1672let HooksDispatcherOnMountInDEV = null;1673let HooksDispatcherOnMountWithHookTypesInDEV = null;1674let HooksDispatcherOnUpdateInDEV = null;1675let HooksDispatcherOnRerenderInDEV = null;1676let InvalidNestedHooksDispatcherOnMountInDEV = null;1677let InvalidNestedHooksDispatcherOnUpdateInDEV = null;1678let InvalidNestedHooksDispatcherOnRerenderInDEV = null;1679if (__DEV__) {1680 const warnInvalidContextAccess = () => {1681 console.error(1682 'Context can only be read while React is rendering. ' +1683 'In classes, you can read it in the render method or getDerivedStateFromProps. ' +1684 'In function components, you can read it directly in the function body, but not ' +1685 'inside Hooks like useReducer() or useMemo().',1686 );1687 };1688 const warnInvalidHookAccess = () => {1689 console.error(1690 'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +1691 'You can only call Hooks at the top level of your React function. ' +1692 'For more information, see ' +1693 'https://reactjs.org/link/rules-of-hooks',1694 );1695 };1696 HooksDispatcherOnMountInDEV = {1697 readContext (1698 context ,1699 observedBits ,1700 ) {1701 return readContext(context, observedBits);1702 },1703 useCallback (callback , deps ) {1704 currentHookNameInDev = 'useCallback';1705 mountHookTypesDev();1706 checkDepsAreArrayDev(deps);1707 return mountCallback(callback, deps);1708 },1709 useContext (1710 context ,1711 observedBits ,1712 ) {1713 currentHookNameInDev = 'useContext';1714 mountHookTypesDev();1715 return readContext(context, observedBits);1716 },1717 useEffect(1718 create ,1719 deps ,1720 ) {1721 currentHookNameInDev = 'useEffect';1722 mountHookTypesDev();1723 checkDepsAreArrayDev(deps);1724 return mountEffect(create, deps);1725 },1726 useImperativeHandle (1727 ref ,1728 create ,1729 deps ,1730 ) {1731 currentHookNameInDev = 'useImperativeHandle';1732 mountHookTypesDev();1733 checkDepsAreArrayDev(deps);1734 return mountImperativeHandle(ref, create, deps);1735 },1736 useLayoutEffect(1737 create ,1738 deps ,1739 ) {1740 currentHookNameInDev = 'useLayoutEffect';1741 mountHookTypesDev();1742 checkDepsAreArrayDev(deps);1743 return mountLayoutEffect(create, deps);1744 },1745 useMemo (create , deps ) {1746 currentHookNameInDev = 'useMemo';1747 mountHookTypesDev();1748 checkDepsAreArrayDev(deps);1749 const prevDispatcher = ReactCurrentDispatcher.current;1750 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1751 try {1752 return mountMemo(create, deps);1753 } finally {1754 ReactCurrentDispatcher.current = prevDispatcher;1755 }1756 },1757 useReducer (1758 reducer ,1759 initialArg ,1760 init ,1761 ) {1762 currentHookNameInDev = 'useReducer';1763 mountHookTypesDev();1764 const prevDispatcher = ReactCurrentDispatcher.current;1765 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1766 try {1767 return mountReducer(reducer, initialArg, init);1768 } finally {1769 ReactCurrentDispatcher.current = prevDispatcher;1770 }1771 },1772 useRef (initialValue ) {1773 currentHookNameInDev = 'useRef';1774 mountHookTypesDev();1775 return mountRef(initialValue);1776 },1777 useState (1778 initialState ,1779 ) {1780 currentHookNameInDev = 'useState';1781 mountHookTypesDev();1782 const prevDispatcher = ReactCurrentDispatcher.current;1783 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1784 try {1785 return mountState(initialState);1786 } finally {1787 ReactCurrentDispatcher.current = prevDispatcher;1788 }1789 },1790 useDebugValue (value , formatterFn ) {1791 currentHookNameInDev = 'useDebugValue';1792 mountHookTypesDev();1793 return mountDebugValue(value, formatterFn);1794 },1795 useDeferredValue (value ) {1796 currentHookNameInDev = 'useDeferredValue';1797 mountHookTypesDev();1798 return mountDeferredValue(value);1799 },1800 useTransition() {1801 currentHookNameInDev = 'useTransition';1802 mountHookTypesDev();1803 return mountTransition();1804 },1805 useMutableSource (1806 source ,1807 getSnapshot ,1808 subscribe ,1809 ) {1810 currentHookNameInDev = 'useMutableSource';1811 mountHookTypesDev();1812 return mountMutableSource(source, getSnapshot, subscribe);1813 },1814 useOpaqueIdentifier() {1815 currentHookNameInDev = 'useOpaqueIdentifier';1816 mountHookTypesDev();1817 return mountOpaqueIdentifier();1818 },1819 unstable_isNewReconciler: enableNewReconciler,1820 };1821 HooksDispatcherOnMountWithHookTypesInDEV = {1822 readContext (1823 context ,1824 observedBits ,1825 ) {1826 return readContext(context, observedBits);1827 },1828 useCallback (callback , deps ) {1829 currentHookNameInDev = 'useCallback';1830 updateHookTypesDev();1831 return mountCallback(callback, deps);1832 },1833 useContext (1834 context ,1835 observedBits ,1836 ) {1837 currentHookNameInDev = 'useContext';1838 updateHookTypesDev();1839 return readContext(context, observedBits);1840 },1841 useEffect(1842 create ,1843 deps ,1844 ) {1845 currentHookNameInDev = 'useEffect';1846 updateHookTypesDev();1847 return mountEffect(create, deps);1848 },1849 useImperativeHandle (1850 ref ,1851 create ,1852 deps ,1853 ) {1854 currentHookNameInDev = 'useImperativeHandle';1855 updateHookTypesDev();1856 return mountImperativeHandle(ref, create, deps);1857 },1858 useLayoutEffect(1859 create ,1860 deps ,1861 ) {1862 currentHookNameInDev = 'useLayoutEffect';1863 updateHookTypesDev();1864 return mountLayoutEffect(create, deps);1865 },1866 useMemo (create , deps ) {1867 currentHookNameInDev = 'useMemo';1868 updateHookTypesDev();1869 const prevDispatcher = ReactCurrentDispatcher.current;1870 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1871 try {1872 return mountMemo(create, deps);1873 } finally {1874 ReactCurrentDispatcher.current = prevDispatcher;1875 }1876 },1877 useReducer (1878 reducer ,1879 initialArg ,1880 init ,1881 ) {1882 currentHookNameInDev = 'useReducer';1883 updateHookTypesDev();1884 const prevDispatcher = ReactCurrentDispatcher.current;1885 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1886 try {1887 return mountReducer(reducer, initialArg, init);1888 } finally {1889 ReactCurrentDispatcher.current = prevDispatcher;1890 }1891 },1892 useRef (initialValue ) {1893 currentHookNameInDev = 'useRef';1894 updateHookTypesDev();1895 return mountRef(initialValue);1896 },1897 useState (1898 initialState ,1899 ) {1900 currentHookNameInDev = 'useState';1901 updateHookTypesDev();1902 const prevDispatcher = ReactCurrentDispatcher.current;1903 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1904 try {1905 return mountState(initialState);1906 } finally {1907 ReactCurrentDispatcher.current = prevDispatcher;1908 }1909 },1910 useDebugValue (value , formatterFn ) {1911 currentHookNameInDev = 'useDebugValue';1912 updateHookTypesDev();1913 return mountDebugValue(value, formatterFn);1914 },1915 useDeferredValue (value ) {1916 currentHookNameInDev = 'useDeferredValue';1917 updateHookTypesDev();1918 return mountDeferredValue(value);1919 },1920 useTransition() {1921 currentHookNameInDev = 'useTransition';1922 updateHookTypesDev();1923 return mountTransition();1924 },1925 useMutableSource (1926 source ,1927 getSnapshot ,1928 subscribe ,1929 ) {1930 currentHookNameInDev = 'useMutableSource';1931 updateHookTypesDev();1932 return mountMutableSource(source, getSnapshot, subscribe);1933 },1934 useOpaqueIdentifier() {1935 currentHookNameInDev = 'useOpaqueIdentifier';1936 updateHookTypesDev();1937 return mountOpaqueIdentifier();1938 },1939 unstable_isNewReconciler: enableNewReconciler,1940 };1941 HooksDispatcherOnUpdateInDEV = {1942 readContext (1943 context ,1944 observedBits ,1945 ) {1946 return readContext(context, observedBits);1947 },1948 useCallback (callback , deps ) {1949 currentHookNameInDev = 'useCallback';1950 updateHookTypesDev();1951 return updateCallback(callback, deps);1952 },1953 useContext (1954 context ,1955 observedBits ,1956 ) {1957 currentHookNameInDev = 'useContext';1958 updateHookTypesDev();1959 return readContext(context, observedBits);1960 },1961 useEffect(1962 create ,1963 deps ,1964 ) {1965 currentHookNameInDev = 'useEffect';1966 updateHookTypesDev();1967 return updateEffect(create, deps);1968 },1969 useImperativeHandle (1970 ref ,1971 create ,1972 deps ,1973 ) {1974 currentHookNameInDev = 'useImperativeHandle';1975 updateHookTypesDev();1976 return updateImperativeHandle(ref, create, deps);1977 },1978 useLayoutEffect(1979 create ,1980 deps ,1981 ) {1982 currentHookNameInDev = 'useLayoutEffect';1983 updateHookTypesDev();1984 return updateLayoutEffect(create, deps);1985 },1986 useMemo (create , deps ) {1987 currentHookNameInDev = 'useMemo';1988 updateHookTypesDev();1989 const prevDispatcher = ReactCurrentDispatcher.current;1990 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1991 try {1992 return updateMemo(create, deps);1993 } finally {1994 ReactCurrentDispatcher.current = prevDispatcher;1995 }1996 },1997 useReducer (1998 reducer ,1999 initialArg ,2000 init ,2001 ) {2002 currentHookNameInDev = 'useReducer';2003 updateHookTypesDev();2004 const prevDispatcher = ReactCurrentDispatcher.current;2005 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2006 try {2007 return updateReducer(reducer, initialArg, init);2008 } finally {2009 ReactCurrentDispatcher.current = prevDispatcher;2010 }2011 },2012 useRef (initialValue ) {2013 currentHookNameInDev = 'useRef';2014 updateHookTypesDev();2015 return updateRef(initialValue);2016 },2017 useState (2018 initialState ,2019 ) {2020 currentHookNameInDev = 'useState';2021 updateHookTypesDev();2022 const prevDispatcher = ReactCurrentDispatcher.current;2023 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2024 try {2025 return updateState(initialState);2026 } finally {2027 ReactCurrentDispatcher.current = prevDispatcher;2028 }2029 },2030 useDebugValue (value , formatterFn ) {2031 currentHookNameInDev = 'useDebugValue';2032 updateHookTypesDev();2033 return updateDebugValue(value, formatterFn);2034 },2035 useDeferredValue (value ) {2036 currentHookNameInDev = 'useDeferredValue';2037 updateHookTypesDev();2038 return updateDeferredValue(value);2039 },2040 useTransition() {2041 currentHookNameInDev = 'useTransition';2042 updateHookTypesDev();2043 return updateTransition();2044 },2045 useMutableSource (2046 source ,2047 getSnapshot ,2048 subscribe ,2049 ) {2050 currentHookNameInDev = 'useMutableSource';2051 updateHookTypesDev();2052 return updateMutableSource(source, getSnapshot, subscribe);2053 },2054 useOpaqueIdentifier() {2055 currentHookNameInDev = 'useOpaqueIdentifier';2056 updateHookTypesDev();2057 return updateOpaqueIdentifier();2058 },2059 unstable_isNewReconciler: enableNewReconciler,2060 };2061 HooksDispatcherOnRerenderInDEV = {2062 readContext (2063 context ,2064 observedBits ,2065 ) {2066 return readContext(context, observedBits);2067 },2068 useCallback (callback , deps ) {2069 currentHookNameInDev = 'useCallback';2070 updateHookTypesDev();2071 return updateCallback(callback, deps);2072 },2073 useContext (2074 context ,2075 observedBits ,2076 ) {2077 currentHookNameInDev = 'useContext';2078 updateHookTypesDev();2079 return readContext(context, observedBits);2080 },2081 useEffect(2082 create ,2083 deps ,2084 ) {2085 currentHookNameInDev = 'useEffect';2086 updateHookTypesDev();2087 return updateEffect(create, deps);2088 },2089 useImperativeHandle (2090 ref ,2091 create ,2092 deps ,2093 ) {2094 currentHookNameInDev = 'useImperativeHandle';2095 updateHookTypesDev();2096 return updateImperativeHandle(ref, create, deps);2097 },2098 useLayoutEffect(2099 create ,2100 deps ,2101 ) {2102 currentHookNameInDev = 'useLayoutEffect';2103 updateHookTypesDev();2104 return updateLayoutEffect(create, deps);2105 },2106 useMemo (create , deps ) {2107 currentHookNameInDev = 'useMemo';2108 updateHookTypesDev();2109 const prevDispatcher = ReactCurrentDispatcher.current;2110 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV;2111 try {2112 return updateMemo(create, deps);2113 } finally {2114 ReactCurrentDispatcher.current = prevDispatcher;2115 }2116 },2117 useReducer (2118 reducer ,2119 initialArg ,2120 init ,2121 ) {2122 currentHookNameInDev = 'useReducer';2123 updateHookTypesDev();2124 const prevDispatcher = ReactCurrentDispatcher.current;2125 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV;2126 try {2127 return rerenderReducer(reducer, initialArg, init);2128 } finally {2129 ReactCurrentDispatcher.current = prevDispatcher;2130 }2131 },2132 useRef (initialValue ) {2133 currentHookNameInDev = 'useRef';2134 updateHookTypesDev();2135 return updateRef(initialValue);2136 },2137 useState (2138 initialState ,2139 ) {2140 currentHookNameInDev = 'useState';2141 updateHookTypesDev();2142 const prevDispatcher = ReactCurrentDispatcher.current;2143 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV;2144 try {2145 return rerenderState(initialState);2146 } finally {2147 ReactCurrentDispatcher.current = prevDispatcher;2148 }2149 },2150 useDebugValue (value , formatterFn ) {2151 currentHookNameInDev = 'useDebugValue';2152 updateHookTypesDev();2153 return updateDebugValue(value, formatterFn);2154 },2155 useDeferredValue (value ) {2156 currentHookNameInDev = 'useDeferredValue';2157 updateHookTypesDev();2158 return rerenderDeferredValue(value);2159 },2160 useTransition() {2161 currentHookNameInDev = 'useTransition';2162 updateHookTypesDev();2163 return rerenderTransition();2164 },2165 useMutableSource (2166 source ,2167 getSnapshot ,2168 subscribe ,2169 ) {2170 currentHookNameInDev = 'useMutableSource';2171 updateHookTypesDev();2172 return updateMutableSource(source, getSnapshot, subscribe);2173 },2174 useOpaqueIdentifier() {2175 currentHookNameInDev = 'useOpaqueIdentifier';2176 updateHookTypesDev();2177 return rerenderOpaqueIdentifier();2178 },2179 unstable_isNewReconciler: enableNewReconciler,2180 };2181 InvalidNestedHooksDispatcherOnMountInDEV = {2182 readContext (2183 context ,2184 observedBits ,2185 ) {2186 warnInvalidContextAccess();2187 return readContext(context, observedBits);2188 },2189 useCallback (callback , deps ) {2190 currentHookNameInDev = 'useCallback';2191 warnInvalidHookAccess();2192 mountHookTypesDev();2193 return mountCallback(callback, deps);2194 },2195 useContext (2196 context ,2197 observedBits ,2198 ) {2199 currentHookNameInDev = 'useContext';2200 warnInvalidHookAccess();2201 mountHookTypesDev();2202 return readContext(context, observedBits);2203 },2204 useEffect(2205 create ,2206 deps ,2207 ) {2208 currentHookNameInDev = 'useEffect';2209 warnInvalidHookAccess();2210 mountHookTypesDev();2211 return mountEffect(create, deps);2212 },2213 useImperativeHandle (2214 ref ,2215 create ,2216 deps ,2217 ) {2218 currentHookNameInDev = 'useImperativeHandle';2219 warnInvalidHookAccess();2220 mountHookTypesDev();2221 return mountImperativeHandle(ref, create, deps);2222 },2223 useLayoutEffect(2224 create ,2225 deps ,2226 ) {2227 currentHookNameInDev = 'useLayoutEffect';2228 warnInvalidHookAccess();2229 mountHookTypesDev();2230 return mountLayoutEffect(create, deps);2231 },2232 useMemo (create , deps ) {2233 currentHookNameInDev = 'useMemo';2234 warnInvalidHookAccess();2235 mountHookTypesDev();2236 const prevDispatcher = ReactCurrentDispatcher.current;2237 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;2238 try {2239 return mountMemo(create, deps);2240 } finally {2241 ReactCurrentDispatcher.current = prevDispatcher;2242 }2243 },2244 useReducer (2245 reducer ,2246 initialArg ,2247 init ,2248 ) {2249 currentHookNameInDev = 'useReducer';2250 warnInvalidHookAccess();2251 mountHookTypesDev();2252 const prevDispatcher = ReactCurrentDispatcher.current;2253 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;2254 try {2255 return mountReducer(reducer, initialArg, init);2256 } finally {2257 ReactCurrentDispatcher.current = prevDispatcher;2258 }2259 },2260 useRef (initialValue ) {2261 currentHookNameInDev = 'useRef';2262 warnInvalidHookAccess();2263 mountHookTypesDev();2264 return mountRef(initialValue);2265 },2266 useState (2267 initialState ,2268 ) {2269 currentHookNameInDev = 'useState';2270 warnInvalidHookAccess();2271 mountHookTypesDev();2272 const prevDispatcher = ReactCurrentDispatcher.current;2273 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;2274 try {2275 return mountState(initialState);2276 } finally {2277 ReactCurrentDispatcher.current = prevDispatcher;2278 }2279 },2280 useDebugValue (value , formatterFn ) {2281 currentHookNameInDev = 'useDebugValue';2282 warnInvalidHookAccess();2283 mountHookTypesDev();2284 return mountDebugValue(value, formatterFn);2285 },2286 useDeferredValue (value ) {2287 currentHookNameInDev = 'useDeferredValue';2288 warnInvalidHookAccess();2289 mountHookTypesDev();2290 return mountDeferredValue(value);2291 },2292 useTransition() {2293 currentHookNameInDev = 'useTransition';2294 warnInvalidHookAccess();2295 mountHookTypesDev();2296 return mountTransition();2297 },2298 useMutableSource (2299 source ,2300 getSnapshot ,2301 subscribe ,2302 ) {2303 currentHookNameInDev = 'useMutableSource';2304 warnInvalidHookAccess();2305 mountHookTypesDev();2306 return mountMutableSource(source, getSnapshot, subscribe);2307 },2308 useOpaqueIdentifier() {2309 currentHookNameInDev = 'useOpaqueIdentifier';2310 warnInvalidHookAccess();2311 mountHookTypesDev();2312 return mountOpaqueIdentifier();2313 },2314 unstable_isNewReconciler: enableNewReconciler,2315 };2316 InvalidNestedHooksDispatcherOnUpdateInDEV = {2317 readContext (2318 context ,2319 observedBits ,2320 ) {2321 warnInvalidContextAccess();2322 return readContext(context, observedBits);2323 },2324 useCallback (callback , deps ) {2325 currentHookNameInDev = 'useCallback';2326 warnInvalidHookAccess();2327 updateHookTypesDev();2328 return updateCallback(callback, deps);2329 },2330 useContext (2331 context ,2332 observedBits ,2333 ) {2334 currentHookNameInDev = 'useContext';2335 warnInvalidHookAccess();2336 updateHookTypesDev();2337 return readContext(context, observedBits);2338 },2339 useEffect(2340 create ,2341 deps ,2342 ) {2343 currentHookNameInDev = 'useEffect';2344 warnInvalidHookAccess();2345 updateHookTypesDev();2346 return updateEffect(create, deps);2347 },2348 useImperativeHandle (2349 ref ,2350 create ,2351 deps ,2352 ) {2353 currentHookNameInDev = 'useImperativeHandle';2354 warnInvalidHookAccess();2355 updateHookTypesDev();2356 return updateImperativeHandle(ref, create, deps);2357 },2358 useLayoutEffect(2359 create ,2360 deps ,2361 ) {2362 currentHookNameInDev = 'useLayoutEffect';2363 warnInvalidHookAccess();2364 updateHookTypesDev();2365 return updateLayoutEffect(create, deps);2366 },2367 useMemo (create , deps ) {2368 currentHookNameInDev = 'useMemo';2369 warnInvalidHookAccess();2370 updateHookTypesDev();2371 const prevDispatcher = ReactCurrentDispatcher.current;2372 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2373 try {2374 return updateMemo(create, deps);2375 } finally {2376 ReactCurrentDispatcher.current = prevDispatcher;2377 }2378 },2379 useReducer (2380 reducer ,2381 initialArg ,2382 init ,2383 ) {2384 currentHookNameInDev = 'useReducer';2385 warnInvalidHookAccess();2386 updateHookTypesDev();2387 const prevDispatcher = ReactCurrentDispatcher.current;2388 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2389 try {2390 return updateReducer(reducer, initialArg, init);2391 } finally {2392 ReactCurrentDispatcher.current = prevDispatcher;2393 }2394 },2395 useRef (initialValue ) {2396 currentHookNameInDev = 'useRef';2397 warnInvalidHookAccess();2398 updateHookTypesDev();2399 return updateRef(initialValue);2400 },2401 useState (2402 initialState ,2403 ) {2404 currentHookNameInDev = 'useState';2405 warnInvalidHookAccess();2406 updateHookTypesDev();2407 const prevDispatcher = ReactCurrentDispatcher.current;2408 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2409 try {2410 return updateState(initialState);2411 } finally {2412 ReactCurrentDispatcher.current = prevDispatcher;2413 }2414 },2415 useDebugValue (value , formatterFn ) {2416 currentHookNameInDev = 'useDebugValue';2417 warnInvalidHookAccess();2418 updateHookTypesDev();2419 return updateDebugValue(value, formatterFn);2420 },2421 useDeferredValue (value ) {2422 currentHookNameInDev = 'useDeferredValue';2423 warnInvalidHookAccess();2424 updateHookTypesDev();2425 return updateDeferredValue(value);2426 },2427 useTransition() {2428 currentHookNameInDev = 'useTransition';2429 warnInvalidHookAccess();2430 updateHookTypesDev();2431 return updateTransition();2432 },2433 useMutableSource (2434 source ,2435 getSnapshot ,2436 subscribe ,2437 ) {2438 currentHookNameInDev = 'useMutableSource';2439 warnInvalidHookAccess();2440 updateHookTypesDev();2441 return updateMutableSource(source, getSnapshot, subscribe);2442 },2443 useOpaqueIdentifier() {2444 currentHookNameInDev = 'useOpaqueIdentifier';2445 warnInvalidHookAccess();2446 updateHookTypesDev();2447 return updateOpaqueIdentifier();2448 },2449 unstable_isNewReconciler: enableNewReconciler,2450 };2451 InvalidNestedHooksDispatcherOnRerenderInDEV = {2452 readContext (2453 context ,2454 observedBits ,2455 ) {2456 warnInvalidContextAccess();2457 return readContext(context, observedBits);2458 },2459 useCallback (callback , deps ) {2460 currentHookNameInDev = 'useCallback';2461 warnInvalidHookAccess();2462 updateHookTypesDev();2463 return updateCallback(callback, deps);2464 },2465 useContext (2466 context ,2467 observedBits ,2468 ) {2469 currentHookNameInDev = 'useContext';2470 warnInvalidHookAccess();2471 updateHookTypesDev();2472 return readContext(context, observedBits);2473 },2474 useEffect(2475 create ,2476 deps ,2477 ) {2478 currentHookNameInDev = 'useEffect';2479 warnInvalidHookAccess();2480 updateHookTypesDev();2481 return updateEffect(create, deps);2482 },2483 useImperativeHandle (2484 ref ,2485 create ,2486 deps ,2487 ) {2488 currentHookNameInDev = 'useImperativeHandle';2489 warnInvalidHookAccess();2490 updateHookTypesDev();2491 return updateImperativeHandle(ref, create, deps);2492 },2493 useLayoutEffect(2494 create ,2495 deps ,2496 ) {2497 currentHookNameInDev = 'useLayoutEffect';2498 warnInvalidHookAccess();2499 updateHookTypesDev();2500 return updateLayoutEffect(create, deps);2501 },2502 useMemo (create , deps ) {2503 currentHookNameInDev = 'useMemo';2504 warnInvalidHookAccess();2505 updateHookTypesDev();2506 const prevDispatcher = ReactCurrentDispatcher.current;2507 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2508 try {2509 return updateMemo(create, deps);2510 } finally {2511 ReactCurrentDispatcher.current = prevDispatcher;2512 }2513 },2514 useReducer (2515 reducer ,2516 initialArg ,2517 init ,2518 ) {2519 currentHookNameInDev = 'useReducer';2520 warnInvalidHookAccess();2521 updateHookTypesDev();2522 const prevDispatcher = ReactCurrentDispatcher.current;2523 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2524 try {2525 return rerenderReducer(reducer, initialArg, init);2526 } finally {2527 ReactCurrentDispatcher.current = prevDispatcher;2528 }2529 },2530 useRef (initialValue ) {2531 currentHookNameInDev = 'useRef';2532 warnInvalidHookAccess();2533 updateHookTypesDev();2534 return updateRef(initialValue);2535 },2536 useState (2537 initialState ,2538 ) {2539 currentHookNameInDev = 'useState';2540 warnInvalidHookAccess();2541 updateHookTypesDev();2542 const prevDispatcher = ReactCurrentDispatcher.current;2543 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2544 try {2545 return rerenderState(initialState);2546 } finally {2547 ReactCurrentDispatcher.current = prevDispatcher;2548 }2549 },2550 useDebugValue (value , formatterFn ) {2551 currentHookNameInDev = 'useDebugValue';2552 warnInvalidHookAccess();2553 updateHookTypesDev();2554 return updateDebugValue(value, formatterFn);2555 },2556 useDeferredValue (value ) {2557 currentHookNameInDev = 'useDeferredValue';2558 warnInvalidHookAccess();2559 updateHookTypesDev();2560 return rerenderDeferredValue(value);2561 },2562 useTransition() {2563 currentHookNameInDev = 'useTransition';2564 warnInvalidHookAccess();2565 updateHookTypesDev();2566 return rerenderTransition();2567 },2568 useMutableSource (2569 source ,2570 getSnapshot ,2571 subscribe ,2572 ) {2573 currentHookNameInDev = 'useMutableSource';2574 warnInvalidHookAccess();2575 updateHookTypesDev();2576 return updateMutableSource(source, getSnapshot, subscribe);2577 },2578 useOpaqueIdentifier() {2579 currentHookNameInDev = 'useOpaqueIdentifier';2580 warnInvalidHookAccess();2581 updateHookTypesDev();2582 return rerenderOpaqueIdentifier();2583 },2584 unstable_isNewReconciler: enableNewReconciler,2585 };...

Full Screen

Full Screen

ReactFiberHooks.old.js

Source:ReactFiberHooks.old.js Github

copy

Full Screen

...1449function updateOpaqueIdentifier() {1450 const id = updateState(undefined)[0];1451 return id;1452}1453function rerenderOpaqueIdentifier() {1454 const id = rerenderState(undefined)[0];1455 return id;1456}1457function dispatchAction (1458 fiber ,1459 queue ,1460 action ,1461) {1462 if (__DEV__) {1463 if (typeof arguments[3] === 'function') {1464 console.error(1465 "State updates from the useState() and useReducer() Hooks don't support the " +1466 'second callback argument. To execute a side effect after ' +1467 'rendering, declare it in the component body with useEffect().',1468 );1469 }1470 }1471 const eventTime = requestEventTime();1472 const lane = requestUpdateLane(fiber);1473 const update = {1474 lane,1475 action,1476 eagerReducer: null,1477 eagerState: null,1478 next: (null ),1479 };1480 // Append the update to the end of the list.1481 const pending = queue.pending;1482 if (pending === null) {1483 // This is the first update. Create a circular list.1484 update.next = update;1485 } else {1486 update.next = pending.next;1487 pending.next = update;1488 }1489 queue.pending = update;1490 const alternate = fiber.alternate;1491 if (1492 fiber === currentlyRenderingFiber ||1493 (alternate !== null && alternate === currentlyRenderingFiber)1494 ) {1495 // This is a render phase update. Stash it in a lazily-created map of1496 // queue -> linked list of updates. After this render pass, we'll restart1497 // and apply the stashed updates on top of the work-in-progress hook.1498 didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;1499 } else {1500 if (1501 fiber.lanes === NoLanes &&1502 (alternate === null || alternate.lanes === NoLanes)1503 ) {1504 // The queue is currently empty, which means we can eagerly compute the1505 // next state before entering the render phase. If the new state is the1506 // same as the current state, we may be able to bail out entirely.1507 const lastRenderedReducer = queue.lastRenderedReducer;1508 if (lastRenderedReducer !== null) {1509 let prevDispatcher;1510 if (__DEV__) {1511 prevDispatcher = ReactCurrentDispatcher.current;1512 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1513 }1514 try {1515 const currentState = (queue.lastRenderedState );1516 const eagerState = lastRenderedReducer(currentState, action);1517 // Stash the eagerly computed state, and the reducer used to compute1518 // it, on the update object. If the reducer hasn't changed by the1519 // time we enter the render phase, then the eager state can be used1520 // without calling the reducer again.1521 update.eagerReducer = lastRenderedReducer;1522 update.eagerState = eagerState;1523 if (is(eagerState, currentState)) {1524 // Fast path. We can bail out without scheduling React to re-render.1525 // It's still possible that we'll need to rebase this update later,1526 // if the component re-renders for a different reason and by that1527 // time the reducer has changed.1528 return;1529 }1530 } catch (error) {1531 // Suppress the error. It will throw again in the render phase.1532 } finally {1533 if (__DEV__) {1534 ReactCurrentDispatcher.current = prevDispatcher;1535 }1536 }1537 }1538 }1539 if (__DEV__) {1540 // $FlowExpectedError - jest isn't a global, and isn't recognized outside of tests1541 if ('undefined' !== typeof jest) {1542 warnIfNotScopedWithMatchingAct(fiber);1543 warnIfNotCurrentlyActingUpdatesInDev(fiber);1544 }1545 }1546 scheduleUpdateOnFiber(fiber, lane, eventTime);1547 }1548 if (__DEV__) {1549 if (enableDebugTracing) {1550 if (fiber.mode & DebugTracingMode) {1551 const name = getComponentName(fiber.type) || 'Unknown';1552 logStateUpdateScheduled(name, lane, action);1553 }1554 }1555 }1556 if (enableSchedulingProfiler) {1557 markStateUpdateScheduled(fiber, lane);1558 }1559}1560export const ContextOnlyDispatcher = {1561 readContext,1562 useCallback: throwInvalidHookError,1563 useContext: throwInvalidHookError,1564 useEffect: throwInvalidHookError,1565 useImperativeHandle: throwInvalidHookError,1566 useLayoutEffect: throwInvalidHookError,1567 useMemo: throwInvalidHookError,1568 useReducer: throwInvalidHookError,1569 useRef: throwInvalidHookError,1570 useState: throwInvalidHookError,1571 useDebugValue: throwInvalidHookError,1572 useDeferredValue: throwInvalidHookError,1573 useTransition: throwInvalidHookError,1574 useMutableSource: throwInvalidHookError,1575 useOpaqueIdentifier: throwInvalidHookError,1576 unstable_isNewReconciler: enableNewReconciler,1577};1578const HooksDispatcherOnMount = {1579 readContext,1580 useCallback: mountCallback,1581 useContext: readContext,1582 useEffect: mountEffect,1583 useImperativeHandle: mountImperativeHandle,1584 useLayoutEffect: mountLayoutEffect,1585 useMemo: mountMemo,1586 useReducer: mountReducer,1587 useRef: mountRef,1588 useState: mountState,1589 useDebugValue: mountDebugValue,1590 useDeferredValue: mountDeferredValue,1591 useTransition: mountTransition,1592 useMutableSource: mountMutableSource,1593 useOpaqueIdentifier: mountOpaqueIdentifier,1594 unstable_isNewReconciler: enableNewReconciler,1595};1596const HooksDispatcherOnUpdate = {1597 readContext,1598 useCallback: updateCallback,1599 useContext: readContext,1600 useEffect: updateEffect,1601 useImperativeHandle: updateImperativeHandle,1602 useLayoutEffect: updateLayoutEffect,1603 useMemo: updateMemo,1604 useReducer: updateReducer,1605 useRef: updateRef,1606 useState: updateState,1607 useDebugValue: updateDebugValue,1608 useDeferredValue: updateDeferredValue,1609 useTransition: updateTransition,1610 useMutableSource: updateMutableSource,1611 useOpaqueIdentifier: updateOpaqueIdentifier,1612 unstable_isNewReconciler: enableNewReconciler,1613};1614const HooksDispatcherOnRerender = {1615 readContext,1616 useCallback: updateCallback,1617 useContext: readContext,1618 useEffect: updateEffect,1619 useImperativeHandle: updateImperativeHandle,1620 useLayoutEffect: updateLayoutEffect,1621 useMemo: updateMemo,1622 useReducer: rerenderReducer,1623 useRef: updateRef,1624 useState: rerenderState,1625 useDebugValue: updateDebugValue,1626 useDeferredValue: rerenderDeferredValue,1627 useTransition: rerenderTransition,1628 useMutableSource: updateMutableSource,1629 useOpaqueIdentifier: rerenderOpaqueIdentifier,1630 unstable_isNewReconciler: enableNewReconciler,1631};1632let HooksDispatcherOnMountInDEV = null;1633let HooksDispatcherOnMountWithHookTypesInDEV = null;1634let HooksDispatcherOnUpdateInDEV = null;1635let HooksDispatcherOnRerenderInDEV = null;1636let InvalidNestedHooksDispatcherOnMountInDEV = null;1637let InvalidNestedHooksDispatcherOnUpdateInDEV = null;1638let InvalidNestedHooksDispatcherOnRerenderInDEV = null;1639if (__DEV__) {1640 const warnInvalidContextAccess = () => {1641 console.error(1642 'Context can only be read while React is rendering. ' +1643 'In classes, you can read it in the render method or getDerivedStateFromProps. ' +1644 'In function components, you can read it directly in the function body, but not ' +1645 'inside Hooks like useReducer() or useMemo().',1646 );1647 };1648 const warnInvalidHookAccess = () => {1649 console.error(1650 'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +1651 'You can only call Hooks at the top level of your React function. ' +1652 'For more information, see ' +1653 'https://reactjs.org/link/rules-of-hooks',1654 );1655 };1656 HooksDispatcherOnMountInDEV = {1657 readContext (1658 context ,1659 observedBits ,1660 ) {1661 return readContext(context, observedBits);1662 },1663 useCallback (callback , deps ) {1664 currentHookNameInDev = 'useCallback';1665 mountHookTypesDev();1666 checkDepsAreArrayDev(deps);1667 return mountCallback(callback, deps);1668 },1669 useContext (1670 context ,1671 observedBits ,1672 ) {1673 currentHookNameInDev = 'useContext';1674 mountHookTypesDev();1675 return readContext(context, observedBits);1676 },1677 useEffect(1678 create ,1679 deps ,1680 ) {1681 currentHookNameInDev = 'useEffect';1682 mountHookTypesDev();1683 checkDepsAreArrayDev(deps);1684 return mountEffect(create, deps);1685 },1686 useImperativeHandle (1687 ref ,1688 create ,1689 deps ,1690 ) {1691 currentHookNameInDev = 'useImperativeHandle';1692 mountHookTypesDev();1693 checkDepsAreArrayDev(deps);1694 return mountImperativeHandle(ref, create, deps);1695 },1696 useLayoutEffect(1697 create ,1698 deps ,1699 ) {1700 currentHookNameInDev = 'useLayoutEffect';1701 mountHookTypesDev();1702 checkDepsAreArrayDev(deps);1703 return mountLayoutEffect(create, deps);1704 },1705 useMemo (create , deps ) {1706 currentHookNameInDev = 'useMemo';1707 mountHookTypesDev();1708 checkDepsAreArrayDev(deps);1709 const prevDispatcher = ReactCurrentDispatcher.current;1710 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1711 try {1712 return mountMemo(create, deps);1713 } finally {1714 ReactCurrentDispatcher.current = prevDispatcher;1715 }1716 },1717 useReducer (1718 reducer ,1719 initialArg ,1720 init ,1721 ) {1722 currentHookNameInDev = 'useReducer';1723 mountHookTypesDev();1724 const prevDispatcher = ReactCurrentDispatcher.current;1725 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1726 try {1727 return mountReducer(reducer, initialArg, init);1728 } finally {1729 ReactCurrentDispatcher.current = prevDispatcher;1730 }1731 },1732 useRef (initialValue ) {1733 currentHookNameInDev = 'useRef';1734 mountHookTypesDev();1735 return mountRef(initialValue);1736 },1737 useState (1738 initialState ,1739 ) {1740 currentHookNameInDev = 'useState';1741 mountHookTypesDev();1742 const prevDispatcher = ReactCurrentDispatcher.current;1743 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1744 try {1745 return mountState(initialState);1746 } finally {1747 ReactCurrentDispatcher.current = prevDispatcher;1748 }1749 },1750 useDebugValue (value , formatterFn ) {1751 currentHookNameInDev = 'useDebugValue';1752 mountHookTypesDev();1753 return mountDebugValue(value, formatterFn);1754 },1755 useDeferredValue (value ) {1756 currentHookNameInDev = 'useDeferredValue';1757 mountHookTypesDev();1758 return mountDeferredValue(value);1759 },1760 useTransition() {1761 currentHookNameInDev = 'useTransition';1762 mountHookTypesDev();1763 return mountTransition();1764 },1765 useMutableSource (1766 source ,1767 getSnapshot ,1768 subscribe ,1769 ) {1770 currentHookNameInDev = 'useMutableSource';1771 mountHookTypesDev();1772 return mountMutableSource(source, getSnapshot, subscribe);1773 },1774 useOpaqueIdentifier() {1775 currentHookNameInDev = 'useOpaqueIdentifier';1776 mountHookTypesDev();1777 return mountOpaqueIdentifier();1778 },1779 unstable_isNewReconciler: enableNewReconciler,1780 };1781 HooksDispatcherOnMountWithHookTypesInDEV = {1782 readContext (1783 context ,1784 observedBits ,1785 ) {1786 return readContext(context, observedBits);1787 },1788 useCallback (callback , deps ) {1789 currentHookNameInDev = 'useCallback';1790 updateHookTypesDev();1791 return mountCallback(callback, deps);1792 },1793 useContext (1794 context ,1795 observedBits ,1796 ) {1797 currentHookNameInDev = 'useContext';1798 updateHookTypesDev();1799 return readContext(context, observedBits);1800 },1801 useEffect(1802 create ,1803 deps ,1804 ) {1805 currentHookNameInDev = 'useEffect';1806 updateHookTypesDev();1807 return mountEffect(create, deps);1808 },1809 useImperativeHandle (1810 ref ,1811 create ,1812 deps ,1813 ) {1814 currentHookNameInDev = 'useImperativeHandle';1815 updateHookTypesDev();1816 return mountImperativeHandle(ref, create, deps);1817 },1818 useLayoutEffect(1819 create ,1820 deps ,1821 ) {1822 currentHookNameInDev = 'useLayoutEffect';1823 updateHookTypesDev();1824 return mountLayoutEffect(create, deps);1825 },1826 useMemo (create , deps ) {1827 currentHookNameInDev = 'useMemo';1828 updateHookTypesDev();1829 const prevDispatcher = ReactCurrentDispatcher.current;1830 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1831 try {1832 return mountMemo(create, deps);1833 } finally {1834 ReactCurrentDispatcher.current = prevDispatcher;1835 }1836 },1837 useReducer (1838 reducer ,1839 initialArg ,1840 init ,1841 ) {1842 currentHookNameInDev = 'useReducer';1843 updateHookTypesDev();1844 const prevDispatcher = ReactCurrentDispatcher.current;1845 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1846 try {1847 return mountReducer(reducer, initialArg, init);1848 } finally {1849 ReactCurrentDispatcher.current = prevDispatcher;1850 }1851 },1852 useRef (initialValue ) {1853 currentHookNameInDev = 'useRef';1854 updateHookTypesDev();1855 return mountRef(initialValue);1856 },1857 useState (1858 initialState ,1859 ) {1860 currentHookNameInDev = 'useState';1861 updateHookTypesDev();1862 const prevDispatcher = ReactCurrentDispatcher.current;1863 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;1864 try {1865 return mountState(initialState);1866 } finally {1867 ReactCurrentDispatcher.current = prevDispatcher;1868 }1869 },1870 useDebugValue (value , formatterFn ) {1871 currentHookNameInDev = 'useDebugValue';1872 updateHookTypesDev();1873 return mountDebugValue(value, formatterFn);1874 },1875 useDeferredValue (value ) {1876 currentHookNameInDev = 'useDeferredValue';1877 updateHookTypesDev();1878 return mountDeferredValue(value);1879 },1880 useTransition() {1881 currentHookNameInDev = 'useTransition';1882 updateHookTypesDev();1883 return mountTransition();1884 },1885 useMutableSource (1886 source ,1887 getSnapshot ,1888 subscribe ,1889 ) {1890 currentHookNameInDev = 'useMutableSource';1891 updateHookTypesDev();1892 return mountMutableSource(source, getSnapshot, subscribe);1893 },1894 useOpaqueIdentifier() {1895 currentHookNameInDev = 'useOpaqueIdentifier';1896 updateHookTypesDev();1897 return mountOpaqueIdentifier();1898 },1899 unstable_isNewReconciler: enableNewReconciler,1900 };1901 HooksDispatcherOnUpdateInDEV = {1902 readContext (1903 context ,1904 observedBits ,1905 ) {1906 return readContext(context, observedBits);1907 },1908 useCallback (callback , deps ) {1909 currentHookNameInDev = 'useCallback';1910 updateHookTypesDev();1911 return updateCallback(callback, deps);1912 },1913 useContext (1914 context ,1915 observedBits ,1916 ) {1917 currentHookNameInDev = 'useContext';1918 updateHookTypesDev();1919 return readContext(context, observedBits);1920 },1921 useEffect(1922 create ,1923 deps ,1924 ) {1925 currentHookNameInDev = 'useEffect';1926 updateHookTypesDev();1927 return updateEffect(create, deps);1928 },1929 useImperativeHandle (1930 ref ,1931 create ,1932 deps ,1933 ) {1934 currentHookNameInDev = 'useImperativeHandle';1935 updateHookTypesDev();1936 return updateImperativeHandle(ref, create, deps);1937 },1938 useLayoutEffect(1939 create ,1940 deps ,1941 ) {1942 currentHookNameInDev = 'useLayoutEffect';1943 updateHookTypesDev();1944 return updateLayoutEffect(create, deps);1945 },1946 useMemo (create , deps ) {1947 currentHookNameInDev = 'useMemo';1948 updateHookTypesDev();1949 const prevDispatcher = ReactCurrentDispatcher.current;1950 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1951 try {1952 return updateMemo(create, deps);1953 } finally {1954 ReactCurrentDispatcher.current = prevDispatcher;1955 }1956 },1957 useReducer (1958 reducer ,1959 initialArg ,1960 init ,1961 ) {1962 currentHookNameInDev = 'useReducer';1963 updateHookTypesDev();1964 const prevDispatcher = ReactCurrentDispatcher.current;1965 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1966 try {1967 return updateReducer(reducer, initialArg, init);1968 } finally {1969 ReactCurrentDispatcher.current = prevDispatcher;1970 }1971 },1972 useRef (initialValue ) {1973 currentHookNameInDev = 'useRef';1974 updateHookTypesDev();1975 return updateRef(initialValue);1976 },1977 useState (1978 initialState ,1979 ) {1980 currentHookNameInDev = 'useState';1981 updateHookTypesDev();1982 const prevDispatcher = ReactCurrentDispatcher.current;1983 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;1984 try {1985 return updateState(initialState);1986 } finally {1987 ReactCurrentDispatcher.current = prevDispatcher;1988 }1989 },1990 useDebugValue (value , formatterFn ) {1991 currentHookNameInDev = 'useDebugValue';1992 updateHookTypesDev();1993 return updateDebugValue(value, formatterFn);1994 },1995 useDeferredValue (value ) {1996 currentHookNameInDev = 'useDeferredValue';1997 updateHookTypesDev();1998 return updateDeferredValue(value);1999 },2000 useTransition() {2001 currentHookNameInDev = 'useTransition';2002 updateHookTypesDev();2003 return updateTransition();2004 },2005 useMutableSource (2006 source ,2007 getSnapshot ,2008 subscribe ,2009 ) {2010 currentHookNameInDev = 'useMutableSource';2011 updateHookTypesDev();2012 return updateMutableSource(source, getSnapshot, subscribe);2013 },2014 useOpaqueIdentifier() {2015 currentHookNameInDev = 'useOpaqueIdentifier';2016 updateHookTypesDev();2017 return updateOpaqueIdentifier();2018 },2019 unstable_isNewReconciler: enableNewReconciler,2020 };2021 HooksDispatcherOnRerenderInDEV = {2022 readContext (2023 context ,2024 observedBits ,2025 ) {2026 return readContext(context, observedBits);2027 },2028 useCallback (callback , deps ) {2029 currentHookNameInDev = 'useCallback';2030 updateHookTypesDev();2031 return updateCallback(callback, deps);2032 },2033 useContext (2034 context ,2035 observedBits ,2036 ) {2037 currentHookNameInDev = 'useContext';2038 updateHookTypesDev();2039 return readContext(context, observedBits);2040 },2041 useEffect(2042 create ,2043 deps ,2044 ) {2045 currentHookNameInDev = 'useEffect';2046 updateHookTypesDev();2047 return updateEffect(create, deps);2048 },2049 useImperativeHandle (2050 ref ,2051 create ,2052 deps ,2053 ) {2054 currentHookNameInDev = 'useImperativeHandle';2055 updateHookTypesDev();2056 return updateImperativeHandle(ref, create, deps);2057 },2058 useLayoutEffect(2059 create ,2060 deps ,2061 ) {2062 currentHookNameInDev = 'useLayoutEffect';2063 updateHookTypesDev();2064 return updateLayoutEffect(create, deps);2065 },2066 useMemo (create , deps ) {2067 currentHookNameInDev = 'useMemo';2068 updateHookTypesDev();2069 const prevDispatcher = ReactCurrentDispatcher.current;2070 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV;2071 try {2072 return updateMemo(create, deps);2073 } finally {2074 ReactCurrentDispatcher.current = prevDispatcher;2075 }2076 },2077 useReducer (2078 reducer ,2079 initialArg ,2080 init ,2081 ) {2082 currentHookNameInDev = 'useReducer';2083 updateHookTypesDev();2084 const prevDispatcher = ReactCurrentDispatcher.current;2085 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV;2086 try {2087 return rerenderReducer(reducer, initialArg, init);2088 } finally {2089 ReactCurrentDispatcher.current = prevDispatcher;2090 }2091 },2092 useRef (initialValue ) {2093 currentHookNameInDev = 'useRef';2094 updateHookTypesDev();2095 return updateRef(initialValue);2096 },2097 useState (2098 initialState ,2099 ) {2100 currentHookNameInDev = 'useState';2101 updateHookTypesDev();2102 const prevDispatcher = ReactCurrentDispatcher.current;2103 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV;2104 try {2105 return rerenderState(initialState);2106 } finally {2107 ReactCurrentDispatcher.current = prevDispatcher;2108 }2109 },2110 useDebugValue (value , formatterFn ) {2111 currentHookNameInDev = 'useDebugValue';2112 updateHookTypesDev();2113 return updateDebugValue(value, formatterFn);2114 },2115 useDeferredValue (value ) {2116 currentHookNameInDev = 'useDeferredValue';2117 updateHookTypesDev();2118 return rerenderDeferredValue(value);2119 },2120 useTransition() {2121 currentHookNameInDev = 'useTransition';2122 updateHookTypesDev();2123 return rerenderTransition();2124 },2125 useMutableSource (2126 source ,2127 getSnapshot ,2128 subscribe ,2129 ) {2130 currentHookNameInDev = 'useMutableSource';2131 updateHookTypesDev();2132 return updateMutableSource(source, getSnapshot, subscribe);2133 },2134 useOpaqueIdentifier() {2135 currentHookNameInDev = 'useOpaqueIdentifier';2136 updateHookTypesDev();2137 return rerenderOpaqueIdentifier();2138 },2139 unstable_isNewReconciler: enableNewReconciler,2140 };2141 InvalidNestedHooksDispatcherOnMountInDEV = {2142 readContext (2143 context ,2144 observedBits ,2145 ) {2146 warnInvalidContextAccess();2147 return readContext(context, observedBits);2148 },2149 useCallback (callback , deps ) {2150 currentHookNameInDev = 'useCallback';2151 warnInvalidHookAccess();2152 mountHookTypesDev();2153 return mountCallback(callback, deps);2154 },2155 useContext (2156 context ,2157 observedBits ,2158 ) {2159 currentHookNameInDev = 'useContext';2160 warnInvalidHookAccess();2161 mountHookTypesDev();2162 return readContext(context, observedBits);2163 },2164 useEffect(2165 create ,2166 deps ,2167 ) {2168 currentHookNameInDev = 'useEffect';2169 warnInvalidHookAccess();2170 mountHookTypesDev();2171 return mountEffect(create, deps);2172 },2173 useImperativeHandle (2174 ref ,2175 create ,2176 deps ,2177 ) {2178 currentHookNameInDev = 'useImperativeHandle';2179 warnInvalidHookAccess();2180 mountHookTypesDev();2181 return mountImperativeHandle(ref, create, deps);2182 },2183 useLayoutEffect(2184 create ,2185 deps ,2186 ) {2187 currentHookNameInDev = 'useLayoutEffect';2188 warnInvalidHookAccess();2189 mountHookTypesDev();2190 return mountLayoutEffect(create, deps);2191 },2192 useMemo (create , deps ) {2193 currentHookNameInDev = 'useMemo';2194 warnInvalidHookAccess();2195 mountHookTypesDev();2196 const prevDispatcher = ReactCurrentDispatcher.current;2197 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;2198 try {2199 return mountMemo(create, deps);2200 } finally {2201 ReactCurrentDispatcher.current = prevDispatcher;2202 }2203 },2204 useReducer (2205 reducer ,2206 initialArg ,2207 init ,2208 ) {2209 currentHookNameInDev = 'useReducer';2210 warnInvalidHookAccess();2211 mountHookTypesDev();2212 const prevDispatcher = ReactCurrentDispatcher.current;2213 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;2214 try {2215 return mountReducer(reducer, initialArg, init);2216 } finally {2217 ReactCurrentDispatcher.current = prevDispatcher;2218 }2219 },2220 useRef (initialValue ) {2221 currentHookNameInDev = 'useRef';2222 warnInvalidHookAccess();2223 mountHookTypesDev();2224 return mountRef(initialValue);2225 },2226 useState (2227 initialState ,2228 ) {2229 currentHookNameInDev = 'useState';2230 warnInvalidHookAccess();2231 mountHookTypesDev();2232 const prevDispatcher = ReactCurrentDispatcher.current;2233 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;2234 try {2235 return mountState(initialState);2236 } finally {2237 ReactCurrentDispatcher.current = prevDispatcher;2238 }2239 },2240 useDebugValue (value , formatterFn ) {2241 currentHookNameInDev = 'useDebugValue';2242 warnInvalidHookAccess();2243 mountHookTypesDev();2244 return mountDebugValue(value, formatterFn);2245 },2246 useDeferredValue (value ) {2247 currentHookNameInDev = 'useDeferredValue';2248 warnInvalidHookAccess();2249 mountHookTypesDev();2250 return mountDeferredValue(value);2251 },2252 useTransition() {2253 currentHookNameInDev = 'useTransition';2254 warnInvalidHookAccess();2255 mountHookTypesDev();2256 return mountTransition();2257 },2258 useMutableSource (2259 source ,2260 getSnapshot ,2261 subscribe ,2262 ) {2263 currentHookNameInDev = 'useMutableSource';2264 warnInvalidHookAccess();2265 mountHookTypesDev();2266 return mountMutableSource(source, getSnapshot, subscribe);2267 },2268 useOpaqueIdentifier() {2269 currentHookNameInDev = 'useOpaqueIdentifier';2270 warnInvalidHookAccess();2271 mountHookTypesDev();2272 return mountOpaqueIdentifier();2273 },2274 unstable_isNewReconciler: enableNewReconciler,2275 };2276 InvalidNestedHooksDispatcherOnUpdateInDEV = {2277 readContext (2278 context ,2279 observedBits ,2280 ) {2281 warnInvalidContextAccess();2282 return readContext(context, observedBits);2283 },2284 useCallback (callback , deps ) {2285 currentHookNameInDev = 'useCallback';2286 warnInvalidHookAccess();2287 updateHookTypesDev();2288 return updateCallback(callback, deps);2289 },2290 useContext (2291 context ,2292 observedBits ,2293 ) {2294 currentHookNameInDev = 'useContext';2295 warnInvalidHookAccess();2296 updateHookTypesDev();2297 return readContext(context, observedBits);2298 },2299 useEffect(2300 create ,2301 deps ,2302 ) {2303 currentHookNameInDev = 'useEffect';2304 warnInvalidHookAccess();2305 updateHookTypesDev();2306 return updateEffect(create, deps);2307 },2308 useImperativeHandle (2309 ref ,2310 create ,2311 deps ,2312 ) {2313 currentHookNameInDev = 'useImperativeHandle';2314 warnInvalidHookAccess();2315 updateHookTypesDev();2316 return updateImperativeHandle(ref, create, deps);2317 },2318 useLayoutEffect(2319 create ,2320 deps ,2321 ) {2322 currentHookNameInDev = 'useLayoutEffect';2323 warnInvalidHookAccess();2324 updateHookTypesDev();2325 return updateLayoutEffect(create, deps);2326 },2327 useMemo (create , deps ) {2328 currentHookNameInDev = 'useMemo';2329 warnInvalidHookAccess();2330 updateHookTypesDev();2331 const prevDispatcher = ReactCurrentDispatcher.current;2332 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2333 try {2334 return updateMemo(create, deps);2335 } finally {2336 ReactCurrentDispatcher.current = prevDispatcher;2337 }2338 },2339 useReducer (2340 reducer ,2341 initialArg ,2342 init ,2343 ) {2344 currentHookNameInDev = 'useReducer';2345 warnInvalidHookAccess();2346 updateHookTypesDev();2347 const prevDispatcher = ReactCurrentDispatcher.current;2348 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2349 try {2350 return updateReducer(reducer, initialArg, init);2351 } finally {2352 ReactCurrentDispatcher.current = prevDispatcher;2353 }2354 },2355 useRef (initialValue ) {2356 currentHookNameInDev = 'useRef';2357 warnInvalidHookAccess();2358 updateHookTypesDev();2359 return updateRef(initialValue);2360 },2361 useState (2362 initialState ,2363 ) {2364 currentHookNameInDev = 'useState';2365 warnInvalidHookAccess();2366 updateHookTypesDev();2367 const prevDispatcher = ReactCurrentDispatcher.current;2368 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2369 try {2370 return updateState(initialState);2371 } finally {2372 ReactCurrentDispatcher.current = prevDispatcher;2373 }2374 },2375 useDebugValue (value , formatterFn ) {2376 currentHookNameInDev = 'useDebugValue';2377 warnInvalidHookAccess();2378 updateHookTypesDev();2379 return updateDebugValue(value, formatterFn);2380 },2381 useDeferredValue (value ) {2382 currentHookNameInDev = 'useDeferredValue';2383 warnInvalidHookAccess();2384 updateHookTypesDev();2385 return updateDeferredValue(value);2386 },2387 useTransition() {2388 currentHookNameInDev = 'useTransition';2389 warnInvalidHookAccess();2390 updateHookTypesDev();2391 return updateTransition();2392 },2393 useMutableSource (2394 source ,2395 getSnapshot ,2396 subscribe ,2397 ) {2398 currentHookNameInDev = 'useMutableSource';2399 warnInvalidHookAccess();2400 updateHookTypesDev();2401 return updateMutableSource(source, getSnapshot, subscribe);2402 },2403 useOpaqueIdentifier() {2404 currentHookNameInDev = 'useOpaqueIdentifier';2405 warnInvalidHookAccess();2406 updateHookTypesDev();2407 return updateOpaqueIdentifier();2408 },2409 unstable_isNewReconciler: enableNewReconciler,2410 };2411 InvalidNestedHooksDispatcherOnRerenderInDEV = {2412 readContext (2413 context ,2414 observedBits ,2415 ) {2416 warnInvalidContextAccess();2417 return readContext(context, observedBits);2418 },2419 useCallback (callback , deps ) {2420 currentHookNameInDev = 'useCallback';2421 warnInvalidHookAccess();2422 updateHookTypesDev();2423 return updateCallback(callback, deps);2424 },2425 useContext (2426 context ,2427 observedBits ,2428 ) {2429 currentHookNameInDev = 'useContext';2430 warnInvalidHookAccess();2431 updateHookTypesDev();2432 return readContext(context, observedBits);2433 },2434 useEffect(2435 create ,2436 deps ,2437 ) {2438 currentHookNameInDev = 'useEffect';2439 warnInvalidHookAccess();2440 updateHookTypesDev();2441 return updateEffect(create, deps);2442 },2443 useImperativeHandle (2444 ref ,2445 create ,2446 deps ,2447 ) {2448 currentHookNameInDev = 'useImperativeHandle';2449 warnInvalidHookAccess();2450 updateHookTypesDev();2451 return updateImperativeHandle(ref, create, deps);2452 },2453 useLayoutEffect(2454 create ,2455 deps ,2456 ) {2457 currentHookNameInDev = 'useLayoutEffect';2458 warnInvalidHookAccess();2459 updateHookTypesDev();2460 return updateLayoutEffect(create, deps);2461 },2462 useMemo (create , deps ) {2463 currentHookNameInDev = 'useMemo';2464 warnInvalidHookAccess();2465 updateHookTypesDev();2466 const prevDispatcher = ReactCurrentDispatcher.current;2467 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2468 try {2469 return updateMemo(create, deps);2470 } finally {2471 ReactCurrentDispatcher.current = prevDispatcher;2472 }2473 },2474 useReducer (2475 reducer ,2476 initialArg ,2477 init ,2478 ) {2479 currentHookNameInDev = 'useReducer';2480 warnInvalidHookAccess();2481 updateHookTypesDev();2482 const prevDispatcher = ReactCurrentDispatcher.current;2483 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2484 try {2485 return rerenderReducer(reducer, initialArg, init);2486 } finally {2487 ReactCurrentDispatcher.current = prevDispatcher;2488 }2489 },2490 useRef (initialValue ) {2491 currentHookNameInDev = 'useRef';2492 warnInvalidHookAccess();2493 updateHookTypesDev();2494 return updateRef(initialValue);2495 },2496 useState (2497 initialState ,2498 ) {2499 currentHookNameInDev = 'useState';2500 warnInvalidHookAccess();2501 updateHookTypesDev();2502 const prevDispatcher = ReactCurrentDispatcher.current;2503 ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;2504 try {2505 return rerenderState(initialState);2506 } finally {2507 ReactCurrentDispatcher.current = prevDispatcher;2508 }2509 },2510 useDebugValue (value , formatterFn ) {2511 currentHookNameInDev = 'useDebugValue';2512 warnInvalidHookAccess();2513 updateHookTypesDev();2514 return updateDebugValue(value, formatterFn);2515 },2516 useDeferredValue (value ) {2517 currentHookNameInDev = 'useDeferredValue';2518 warnInvalidHookAccess();2519 updateHookTypesDev();2520 return rerenderDeferredValue(value);2521 },2522 useTransition() {2523 currentHookNameInDev = 'useTransition';2524 warnInvalidHookAccess();2525 updateHookTypesDev();2526 return rerenderTransition();2527 },2528 useMutableSource (2529 source ,2530 getSnapshot ,2531 subscribe ,2532 ) {2533 currentHookNameInDev = 'useMutableSource';2534 warnInvalidHookAccess();2535 updateHookTypesDev();2536 return updateMutableSource(source, getSnapshot, subscribe);2537 },2538 useOpaqueIdentifier() {2539 currentHookNameInDev = 'useOpaqueIdentifier';2540 warnInvalidHookAccess();2541 updateHookTypesDev();2542 return rerenderOpaqueIdentifier();2543 },2544 unstable_isNewReconciler: enableNewReconciler,2545 };...

Full Screen

Full Screen

ReactFiberHooks.js

Source:ReactFiberHooks.js Github

copy

Full Screen

1import ReactCurrentDispatcher from "../react/ReactCurrentDispatcher";2import { requestEventTime, requestUpdateLane } from "./ReactFiberWorkLoop";3import {4 Update as UpdateEffect,5 Passive as PassiveEffect,6} from "./ReactFiberFlags";7import {8 HasEffect as HookHasEffect,9 Layout as HookLayout,10 Passive as HookPassive,11} from "./ReactHookEffectTags";12// The work-in-progress fiber. I've named it differently to distinguish it from13// the work-in-progress hook.14let currentlyRenderingFiber = null;15// Hooks are stored as a linked list on the fiber's memoizedState field. The16// current hook list is the list that belongs to the current fiber. The17// work-in-progress hook list is a new list that will be added to the18// work-in-progress fiber.19// Hooks 用链表结构, 存贮在fiber's memoizedState字段20// Hook | null21let currentHook = null;22// Hook | null23let workInProgressHook = null;24// Whether an update was scheduled at any point during the render phase. This25// does not get reset if we do another render pass; only when we're completely26// finished evaluating this component. This is an optimization so we know27// whether we need to clear render phase updates after a throw.28let didScheduleRenderPhaseUpdate = false;29// Where an update was scheduled only during the current render pass. This30// gets reset after each attempt.31// TODO: Maybe there's some way to consolidate this with32// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`.33let didScheduleRenderPhaseUpdateDuringThisPass = false;34export function renderWithHooks(35 // null36 current,37 workInProgress,38 // 这里是函数组件, 其实就是wip.type39 Component,40 // wip.props41 props,42 // context43 secondArg,44 nextRenderLanes45) {46 renderLanes = nextRenderLanes;47 currentlyRenderingFiber = workInProgress;48 // 为何这边就已经清空 memoizedState 和 updateQueue 了?49 workInProgress.memoizedState = null;50 workInProgress.updateQueue = null;51 workInProgress.lanes = NoLanes;52 // The following should have already been reset53 // currentHook = null;54 // workInProgressHook = null;55 // didScheduleRenderPhaseUpdate = false;56 // TODO Warn if no hooks are used at all during mount, then some are used during update.57 // Currently we will identify the update render as a mount because memoizedState === null.58 // This is tricky because it's valid for certain types of components (e.g. React.lazy)59 // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used.60 // Non-stateful hooks (e.g. context) don't get added to memoizedState,61 // so memoizedState would be null during updates and mounts.62 // Dispatcher 跟useState有关63 ReactCurrentDispatcher.current =64 current === null || current.memoizedState === null65 ? HooksDispatcherOnMount66 : HooksDispatcherOnUpdate;67 // 直接执行组件函数, 得到一个 jsx object68 let children = Component(props, secondArg);69 // Check if there was a render phase update70 if (didScheduleRenderPhaseUpdateDuringThisPass) {71 // Keep rendering in a loop for as long as render phase updates continue to72 // be scheduled. Use a counter to prevent infinite loops.73 let numberOfReRenders = 0;74 do {75 didScheduleRenderPhaseUpdateDuringThisPass = false;76 invariant(77 numberOfReRenders < RE_RENDER_LIMIT,78 "Too many re-renders. React limits the number of renders to prevent " +79 "an infinite loop."80 );81 numberOfReRenders += 1;82 // Start over from the beginning of the list83 currentHook = null;84 workInProgressHook = null;85 workInProgress.updateQueue = null;86 ReactCurrentDispatcher.current = HooksDispatcherOnRerender;87 children = Component(props, secondArg);88 } while (didScheduleRenderPhaseUpdateDuringThisPass);89 }90 // We can assume the previous dispatcher is always this one, since we set it91 // at the beginning of the render phase and there's no re-entrancy.92 ReactCurrentDispatcher.current = ContextOnlyDispatcher;93 // This check uses currentHook so that it works the same in DEV and prod bundles.94 // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles.95 const didRenderTooFewHooks =96 currentHook !== null && currentHook.next !== null;97 renderLanes = NoLanes;98 currentlyRenderingFiber = null;99 currentHook = null;100 workInProgressHook = null;101 didScheduleRenderPhaseUpdate = false;102 invariant(103 !didRenderTooFewHooks,104 "Rendered fewer hooks than expected. This may be caused by an accidental " +105 "early return statement."106 );107 return children;108}109function mountWorkInProgressHook() {110 const hook = {111 memoizedState: null,112 baseState: null,113 baseQueue: null,114 queue: null,115 next: null,116 };117 if (workInProgressHook === null) {118 // This is the first hook in the list119 currentlyRenderingFiber.memoizedState = workInProgressHook = hook;120 } else {121 // 一个函数组件里面, 两个以上的hook就走这里, 链起来了~122 // Append to the end of the list123 workInProgressHook = workInProgressHook.next = hook;124 }125 return workInProgressHook;126}127function createFunctionComponentUpdateQueue() {128 return {129 lastEffect: null,130 };131}132/**133 * 把tag为 HookHasEffect|HookPassive的effect压入fiber.updateQueue134 */135function pushEffect(tag, create, destroy, deps) {136 const effect = {137 tag,138 create,139 destroy,140 deps,141 // Circular142 next: null,143 };144 // 在我学习的例子里, 这个fiber是App函数组件, 对应的fiber节点是没有updateQueue的(创建的时候就没有初始化)145 let componentUpdateQueue = currentlyRenderingFiber.updateQueue;146 if (componentUpdateQueue === null) {147 componentUpdateQueue = createFunctionComponentUpdateQueue();148 currentlyRenderingFiber.updateQueue = componentUpdateQueue;149 componentUpdateQueue.lastEffect = effect.next = effect;150 } else {151 // 这里跟updateQueue.shared.pending那个双循环有些不一样,152 const lastEffect = componentUpdateQueue.lastEffect;153 if (lastEffect === null) {154 componentUpdateQueue.lastEffect = effect.next = effect;155 } else {156 const firstEffect = lastEffect.next;157 lastEffect.next = effect;158 effect.next = firstEffect;159 componentUpdateQueue.lastEffect = effect;160 }161 }162 return effect;163}164function mountEffectImpl(fiberFlags, hookFlags, create, deps) {165 const hook = mountWorkInProgressHook();166 const nextDeps = deps === undefined ? null : deps;167 // 哦吼, 就在这, 这个fiber上有了 PassiveEffect168 // 在我学的例子里, 对于component App, 其flags在创建的时候169 // 由 placeSingleChild 函数打上 Placement = 2170 // 这里再跟 UpdateEffect | PassiveEffect 做合并171 currentlyRenderingFiber.flags |= fiberFlags;172 // 只是压入updateQueue, **并不执行**173 // 注意, 这里destroy暂时为undefined, 因为destroy函数是create函数的返回值174 hook.memoizedState = pushEffect(175 HookHasEffect | hookFlags,176 create,177 undefined,178 nextDeps179 );180}181function mountEffect(create, deps) {182 return mountEffectImpl(183 UpdateEffect | PassiveEffect,184 HookPassive,185 create,186 deps187 );188}189function mountState(initialState) {190 // wip.memoizedState 塞一个空的hook对象,作为hook单链表的起点(?)191 const hook = mountWorkInProgressHook();192 if (typeof initialState === "function") {193 // useState的初始状态是函数, 这里执行函数, 返回值赋值给initialState194 initialState = initialState();195 }196 hook.memoizedState = hook.baseState = initialState;197 const queue = (hook.queue = {198 pending: null,199 dispatch: null,200 lastRenderedReducer: basicStateReducer,201 lastRenderedState: initialState,202 });203 // const [a, setA] = useState('a')204 // setA 就是这里的 dispatchAction205 const dispatch = (queue.dispatch = dispatchAction.bind(206 null,207 currentlyRenderingFiber,208 queue209 ));210 return [hook.memoizedState, dispatch];211}212// 这函数回头再看213function dispatchAction(fiber, queue, action) {214 const eventTime = requestEventTime();215 const lane = requestUpdateLane(fiber);216 const update = {217 lane,218 action,219 eagerReducer: null,220 eagerState: null,221 next: null,222 };223 // Append the update to the end of the list.224 const pending = queue.pending;225 if (pending === null) {226 // This is the first update. Create a circular list.227 update.next = update;228 } else {229 update.next = pending.next;230 pending.next = update;231 }232 queue.pending = update;233 const alternate = fiber.alternate;234 if (235 fiber === currentlyRenderingFiber ||236 (alternate !== null && alternate === currentlyRenderingFiber)237 ) {238 // This is a render phase update. Stash it in a lazily-created map of239 // queue -> linked list of updates. After this render pass, we'll restart240 // and apply the stashed updates on top of the work-in-progress hook.241 didScheduleRenderPhaseUpdateDuringThisPass =242 didScheduleRenderPhaseUpdate = true;243 } else {244 if (245 fiber.lanes === NoLanes &&246 (alternate === null || alternate.lanes === NoLanes)247 ) {248 // The queue is currently empty, which means we can eagerly compute the249 // next state before entering the render phase. If the new state is the250 // same as the current state, we may be able to bail out entirely.251 const lastRenderedReducer = queue.lastRenderedReducer;252 if (lastRenderedReducer !== null) {253 let prevDispatcher;254 try {255 const currentState = queue.lastRenderedState;256 const eagerState = lastRenderedReducer(currentState, action);257 // Stash the eagerly computed state, and the reducer used to compute258 // it, on the update object. If the reducer hasn't changed by the259 // time we enter the render phase, then the eager state can be used260 // without calling the reducer again.261 update.eagerReducer = lastRenderedReducer;262 update.eagerState = eagerState;263 if (is(eagerState, currentState)) {264 // Fast path. We can bail out without scheduling React to re-render.265 // It's still possible that we'll need to rebase this update later,266 // if the component re-renders for a different reason and by that267 // time the reducer has changed.268 return;269 }270 } catch (error) {271 // Suppress the error. It will throw again in the render phase.272 }273 }274 }275 // 开始render阶段咯276 scheduleUpdateOnFiber(fiber, lane, eventTime);277 }278}279export const ContextOnlyDispatcher = {280 readContext,281 useCallback: throwInvalidHookError,282 useContext: throwInvalidHookError,283 useEffect: throwInvalidHookError,284 useImperativeHandle: throwInvalidHookError,285 useLayoutEffect: throwInvalidHookError,286 useMemo: throwInvalidHookError,287 useReducer: throwInvalidHookError,288 useRef: throwInvalidHookError,289 useState: throwInvalidHookError,290 useDebugValue: throwInvalidHookError,291 useDeferredValue: throwInvalidHookError,292 useTransition: throwInvalidHookError,293 useMutableSource: throwInvalidHookError,294 useOpaqueIdentifier: throwInvalidHookError,295 unstable_isNewReconciler: enableNewReconciler,296};297const HooksDispatcherOnMount = {298 readContext,299 useCallback: mountCallback,300 useContext: readContext,301 useEffect: mountEffect,302 useImperativeHandle: mountImperativeHandle,303 useLayoutEffect: mountLayoutEffect,304 useMemo: mountMemo,305 useReducer: mountReducer,306 useRef: mountRef,307 useState: mountState,308 useDebugValue: mountDebugValue,309 useDeferredValue: mountDeferredValue,310 useTransition: mountTransition,311 useMutableSource: mountMutableSource,312 useOpaqueIdentifier: mountOpaqueIdentifier,313 unstable_isNewReconciler: enableNewReconciler,314};315const HooksDispatcherOnUpdate = {316 readContext,317 useCallback: updateCallback,318 useContext: readContext,319 useEffect: updateEffect,320 useImperativeHandle: updateImperativeHandle,321 useLayoutEffect: updateLayoutEffect,322 useMemo: updateMemo,323 useReducer: updateReducer,324 useRef: updateRef,325 useState: updateState,326 useDebugValue: updateDebugValue,327 useDeferredValue: updateDeferredValue,328 useTransition: updateTransition,329 useMutableSource: updateMutableSource,330 useOpaqueIdentifier: updateOpaqueIdentifier,331 unstable_isNewReconciler: enableNewReconciler,332};333const HooksDispatcherOnRerender = {334 readContext,335 useCallback: updateCallback,336 useContext: readContext,337 useEffect: updateEffect,338 useImperativeHandle: updateImperativeHandle,339 useLayoutEffect: updateLayoutEffect,340 useMemo: updateMemo,341 useReducer: rerenderReducer,342 useRef: updateRef,343 useState: rerenderState,344 useDebugValue: updateDebugValue,345 useDeferredValue: rerenderDeferredValue,346 useTransition: rerenderTransition,347 useMutableSource: updateMutableSource,348 useOpaqueIdentifier: rerenderOpaqueIdentifier,349 unstable_isNewReconciler: enableNewReconciler,...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { rerenderOpaqueIdentifier } = require('@playwright/test');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.waitForSelector('input[name="q"]');8 await rerenderOpaqueIdentifier(page, 'input[name="q"]');9 await page.fill('input[name="q"]', 'Hello World');10 await page.waitForSelector('input[value="Google Search"]');11 await page.click('input[value="Google Search"]');12 await page.waitForSelector('#result-stats');13 await page.screenshot({ path: 'example.png' });14 await browser.close();15})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const pw = require('playwright');2(async () => {3 const browser = await pw.chromium.launch();4 const page = await browser.newPage();5 await page.evaluate(() => {6 const div = document.createElement('div');7 div.id = 'test';8 document.body.appendChild(div);9 });10 const element = await page.$('#test');11 await element.rerenderOpaqueIdentifier();12 await browser.close();13})();14 at CDPSession.send (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\protocol\connection.js:87:23)15 at Object.sendWithErrorHandling (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\protocol\helper.js:65:15)16 at async ExecutionContext._evaluateInternal (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\dom.js:98:25)17 at async ExecutionContext.evaluate (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\dom.js:38:16)18 at async ElementHandle._evaluateInUtility (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\dom.js:1059:17)19 at async ElementHandle._rerenderOpaqueIdentifier (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\dom.js:1072:16)20 at async ElementHandle.rerenderOpaqueIdentifier (C:\Users\Akshay\Documents\GitHub\playwright\packages\playwright\lib\dom.js:1066:16)21 at async Object.<anonymous> (C:\Users\Akshay\Documents\GitHub\playwright\test.js:11

Full Screen

Using AI Code Generation

copy

Full Screen

1const { firefox } = require('playwright');2const { rerenderOpaqueIdentifier } = require('playwright/lib/internal/api');3(async () => {4 const browser = await firefox.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.waitForSelector('text=Get started');8 await rerenderOpaqueIdentifier(page, 'text=Get started');9 await page.screenshot({ path: 'example.png' });10 await browser.close();11})();12async function rerenderOpaqueIdentifier(page, opaqueIdentifier) {13 const { frame, element } = await page._delegate.locatorForOpaqueId(opaqueIdentifier);14 if (element)15 return frame.evaluate(element => element.rerender(), element);16 return frame.evaluate(opaqueId => document.getElementById(opaqueId).rerender(), opaqueIdentifier);17}18Locator.prototype._delegate = {19 locatorForOpaqueId: async function(opaqueId) {20 const [frame, element] = await this._page._delegate.locatorForOpaqueId(opaqueId);21 return { frame, element };22 },23};24Page.prototype._delegate = {25 locatorForOpaqueId: async function(opaqueId) {26 const frame = this._mainFrame;27 const element = await frame._delegate.locatorForOpaqueId(opaqueId);28 return [frame, element];29 },30};31Frame.prototype._delegate = {32 locatorForOpaqueId: async function(opaqueId) {33 return this.evaluateHandle(opaqueId => document.getElementById(opaqueId), opaqueId);34 },35};36ElementHandle.prototype.rerender = function() {37};38ElementHandle.prototype._delegate = {39 locatorForOpaqueId: async function(opaqueId) {40 return this.evaluateHandle(opaqueId => document.getElementById(opaqueId), opaqueId);41 },42};43ElementHandle.prototype._delegate = {44 locatorForOpaqueId: async function(opaqueId) {45 return this.evaluateHandle(opaqueId => document.getElementById(opaqueId), opaque

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 const context = await page.context();6 const frame = await page.mainFrame();7 await frame.rerenderOpaqueIdentifier('opaqueId');8 await browser.close();9})();10import { chromium } from 'playwright';11(async () => {12 const browser = await chromium.launch();13 const page = await browser.newPage();14 const context = await page.context();15 const frame = await page.mainFrame();16 await frame.rerenderOpaqueIdentifier('opaqueId');17 await browser.close();18})();19from playwright.sync_api import sync_playwright20with sync_playwright() as p:21 browser = p.chromium.launch()22 page = browser.new_page()23 context = page.context()24 frame = page.main_frame()25 frame.rerender_opaque_identifier('opaqueId')26 browser.close()27import com.microsoft.playwright.*;28public class Example {29 public static void main(String[] args) {30 try (Playwright playwright = Playwright.create()) {31 BrowserType chromium = playwright.chromium();32 Browser browser = chromium.launch();33 Page page = browser.newPage();34 Context context = page.context();35 Frame frame = page.mainFrame();36 frame.rerenderOpaqueIdentifier("opaqueId");37 browser.close();38 }39 }40}41int main(int argc, char** argv) {42 using namespace playwright;43 auto playwright = Playwright::create();44 auto browser = playwright->chromium()->launch();45 auto page = browser->newPage();46 auto context = page->context();47 auto frame = page->mainFrame();48 frame->rerenderOpaqueIdentifier("opaqueId");49 browser->close();50 return 0;51}52using Microsoft.Playwright;53{54 static async Task Main(string[] args)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { rerenderOpaqueIdentifier } = require('playwright');2const { rerenderOpaqueIdentifier } = require('playwright');3const { chromium } = require('playwright');4(async () => {5 const browser = await chromium.launch();6 const context = await browser.newContext();7 const page = await context.newPage();8 const element = await page.$('text=Get started');9 await rerenderOpaqueIdentifier(element);10 await element.click();11 await page.screenshot({ path: 'example.png' });12 await browser.close();13})();14const { rerenderOpaqueIdentifier } = require('playwright');15const { chromium } = require('playwright');16(async () => {17 const browser = await chromium.launch();18 const context = await browser.newContext();19 const page = await context.newPage();20 const element = await page.$('text=Get started');21 await rerenderOpaqueIdentifier(element);22 await element.click();23 await page.screenshot({ path: 'example.png' });24 await browser.close();25})();26const { rerenderOpaqueIdentifier } = require('playwright');27const { chromium } = require('playwright');28(async () => {29 const browser = await chromium.launch();30 const context = await browser.newContext();31 const page = await context.newPage();32 const element = await page.$('text=Get started');33 await rerenderOpaqueIdentifier(element);34 await element.click();35 await page.screenshot({ path: 'example.png' });36 await browser.close();37})();38const { rerenderOpaqueIdentifier } = require('playwright');39const { chromium } = require('playwright');40(async () => {

Full Screen

Using AI Code Generation

copy

Full Screen

1const { Playwright } = require('playwright');2const playwright = new Playwright();3const { chromium } = playwright;4const browser = await chromium.launch();5const page = await browser.newPage();6const handle = await page.evaluateHandle(() => document.body);7const id = await page._delegate.rerenderOpaqueIdentifier(handle);8console.log(id);9await browser.close();10const { Playwright } = require('playwright');11const playwright = new Playwright();12const { chromium } = playwright;13const browser = await chromium.launch();14const page = await browser.newPage();15const handle = await page.evaluateHandle(() => document.body);16const id = await page._delegate.rerenderOpaqueIdentifier(handle);17console.log(id);18await browser.close();19const { Playwright } = require('playwright');20const playwright = new Playwright();21const { chromium } = playwright;22const browser = await chromium.launch();23const page = await browser.newPage();24const handle = await page.evaluateHandle(() => document.body);

Full Screen

Using AI Code Generation

copy

Full Screen

1const { rerenderOpaqueIdentifier } = require('@playwright/test/lib/rerenderOpaqueIdentifier');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4 const rerendered = await rerenderOpaqueIdentifier(page, 'test-id');5 console.log(rerendered);6});7const { test } = require('@playwright/test');8test('test', async ({ page }) => {9 const rerendered = await rerenderOpaqueIdentifier(page, 'test-id');10 console.log(rerendered);11});12 1 passed (1s)13const { rerenderOpaqueIdentifier } = require('@playwright/test/lib/rerenderOpaqueIdentifier');14module.exports = {15 use: {16 },17};18 1 passed (1s)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');2rerenderOpaqueIdentifier('opaque-id');3const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');4rerenderOpaqueIdentifier('opaque-id');5const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');6rerenderOpaqueIdentifier('opaque-id');7const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');8rerenderOpaqueIdentifier('opaque-id');9const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');10rerenderOpaqueIdentifier('opaque-id');11const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');12rerenderOpaqueIdentifier('opaque-id');13const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');14rerenderOpaqueIdentifier('opaque-id');15const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');16rerenderOpaqueIdentifier('opaque-id');17const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');18rerenderOpaqueIdentifier('opaque-id');19const { rerenderOpaqueIdentifier } = require('playwright/lib/server/dom.js');20rerenderOpaqueIdentifier('opaque-id');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2const { createPage } = require('playwright/lib/server/browserContext');3const { rerenderOpaqueIdentifier } = require('playwright/lib/server/browserContext');4(async () => {5 const browser = await chromium.launch();6 const context = await browser.newContext();7 const page = await context.newPage();8 const element = await page.$('text=Get started');9 const id = await rerenderOpaqueIdentifier(page, element);10 await page.waitForSelector(`[data-identifier="${id}"]`);11 await browser.close();12})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const {chromium} = require('playwright');2(async () => {3 const browser = await chromium.launch({headless: false});4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.click('text="I agree"');7 await page.waitForTimeout(3000);8 const element = await page.$('input[title="Search"]');9 const identifier = await page.evaluate((element) => {10 return window.playwright.getOpaqueIdentifier(element);11 }, element);12 await page.evaluate((identifier) => {13 window.playwright.rerenderOpaqueIdentifier(identifier);14 }, identifier);15 await page.waitForTimeout(5000);16 await browser.close();17})();

Full Screen

Playwright tutorial

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.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful