From dc3c2fb027bc468237b161cd97a676becb3b0dec Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Wed, 10 Mar 2021 21:20:57 -0700 Subject: [PATCH] Flip tuple order of useTransition --- .../ESLintRuleExhaustiveDeps-test.js | 8 +++--- .../src/ExhaustiveDeps.js | 6 +++-- .../react-debug-tools/src/ReactDebugHooks.js | 4 +-- .../InspectedElementErrorsAndWarningsTree.js | 4 +-- .../src/devtools/views/Components/KeyValue.js | 2 +- .../src/server/ReactPartialRendererHooks.js | 4 +-- .../src/ReactFiberHooks.new.js | 26 +++++++++---------- .../src/ReactFiberHooks.old.js | 26 +++++++++---------- .../src/ReactInternalTypes.js | 2 +- .../src/__tests__/ReactHooks-test.internal.js | 2 +- .../ReactHooksWithNoopRenderer-test.js | 7 +++-- .../ReactSuspenseWithNoopRenderer-test.js | 11 +++----- .../src/__tests__/ReactTransition-test.js | 4 +-- packages/react/src/ReactHooks.js | 2 +- 14 files changed, 53 insertions(+), 55 deletions(-) diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 2a2786dca8850..245f3509a0114 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -604,10 +604,10 @@ const tests = { const [state4, dispatch2] = React.useReducer(); const [state5, maybeSetState] = useFunnyState(); const [state6, maybeDispatch] = useFunnyReducer(); - const [startTransition1] = useTransition(); - const [startTransition2, isPending2] = useTransition(); - const [startTransition3] = React.useTransition(); - const [startTransition4, isPending4] = React.useTransition(); + const [isPending1] = useTransition(); + const [isPending2, startTransition2] = useTransition(); + const [isPending3] = React.useTransition(); + const [isPending4, startTransition4] = React.useTransition(); const mySetState = useCallback(() => {}, []); let myDispatch = useCallback(() => {}, []); diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index ee259b2d37cd6..f05a9e77e07e6 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -253,12 +253,14 @@ export default { } } } else if (name === 'useTransition') { + // Only consider second value in initializing tuple stable. if ( id.type === 'ArrayPattern' && + id.elements.length === 2 && Array.isArray(resolved.identifiers) ) { - // Is first tuple value the same reference we're checking? - if (id.elements[0] === resolved.identifiers[0]) { + // Is second tuple value the same reference we're checking?g + if (id.elements[1] === resolved.identifiers[0]) { // Setter is stable. return true; } diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index eb7a8f6d4ef14..efacbc5ec4a7a 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -271,7 +271,7 @@ function useMutableSource( return value; } -function useTransition(): [(() => void) => void, boolean] { +function useTransition(): [boolean, (() => void) => void] { // useTransition() composes multiple hooks internally. // Advance the current hook index the same number of times // so that subsequent hooks have the right memoized state. @@ -282,7 +282,7 @@ function useTransition(): [(() => void) => void, boolean] { stackError: new Error(), value: undefined, }); - return [callback => {}, false]; + return [false, callback => {}]; } function useDeferredValue(value: T): T { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js index 3b7aaca3216d5..83d3721a53dc6 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js @@ -41,8 +41,8 @@ export default function InspectedElementErrorsAndWarningsTree({ const refresh = useCacheRefresh(); const [ - startClearErrorsTransition, isErrorsTransitionPending, + startClearErrorsTransition, ] = useTransition(); const clearErrorsForInspectedElement = () => { const {id} = inspectedElement; @@ -60,8 +60,8 @@ export default function InspectedElementErrorsAndWarningsTree({ }; const [ - startClearWarningsTransition, isWarningsTransitionPending, + startClearWarningsTransition, ] = useTransition(); const clearWarningsForInspectedElement = () => { const {id} = inspectedElement; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js index aa5b1bc56eec4..b39a6d154562a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js @@ -90,7 +90,7 @@ export default function KeyValue({ isReadOnly = value[meta.readonly]; } - const [startInspectPathsTransition, isInspectPathsPending] = useTransition(); + const [isInspectPathsPending, startInspectPathsTransition] = useTransition(); const toggleIsOpen = () => { if (isOpen) { setIsOpen(false); diff --git a/packages/react-dom/src/server/ReactPartialRendererHooks.js b/packages/react-dom/src/server/ReactPartialRendererHooks.js index 50edb72c2844a..1e9678cf3da8d 100644 --- a/packages/react-dom/src/server/ReactPartialRendererHooks.js +++ b/packages/react-dom/src/server/ReactPartialRendererHooks.js @@ -473,12 +473,12 @@ function useDeferredValue(value: T): T { return value; } -function useTransition(): [(callback: () => void) => void, boolean] { +function useTransition(): [boolean, (callback: () => void) => void] { resolveCurrentlyRenderingComponent(); const startTransition = callback => { callback(); }; - return [startTransition, false]; + return [false, startTransition]; } function useOpaqueIdentifier(): OpaqueIDType { diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 9eb089d07d7a5..2731475e9b2ce 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -1728,27 +1728,27 @@ function startTransition(setPending, callback) { } } -function mountTransition(): [(() => void) => void, boolean] { +function mountTransition(): [boolean, (() => void) => void] { const [isPending, setPending] = mountState(false); // The `start` method never changes. const start = startTransition.bind(null, setPending); const hook = mountWorkInProgressHook(); hook.memoizedState = start; - return [start, isPending]; + return [isPending, start]; } -function updateTransition(): [(() => void) => void, boolean] { +function updateTransition(): [boolean, (() => void) => void] { const [isPending] = updateState(false); const hook = updateWorkInProgressHook(); const start = hook.memoizedState; - return [start, isPending]; + return [isPending, start]; } -function rerenderTransition(): [(() => void) => void, boolean] { +function rerenderTransition(): [boolean, (() => void) => void] { const [isPending] = rerenderState(false); const hook = updateWorkInProgressHook(); const start = hook.memoizedState; - return [start, isPending]; + return [isPending, start]; } let isUpdatingOpaqueValueInRenderPhase = false; @@ -2294,7 +2294,7 @@ if (__DEV__) { mountHookTypesDev(); return mountDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; mountHookTypesDev(); return mountTransition(); @@ -2424,7 +2424,7 @@ if (__DEV__) { updateHookTypesDev(); return mountDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; updateHookTypesDev(); return mountTransition(); @@ -2554,7 +2554,7 @@ if (__DEV__) { updateHookTypesDev(); return updateDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; updateHookTypesDev(); return updateTransition(); @@ -2685,7 +2685,7 @@ if (__DEV__) { updateHookTypesDev(); return rerenderDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; updateHookTypesDev(); return rerenderTransition(); @@ -2827,7 +2827,7 @@ if (__DEV__) { mountHookTypesDev(); return mountDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; warnInvalidHookAccess(); mountHookTypesDev(); @@ -2972,7 +2972,7 @@ if (__DEV__) { updateHookTypesDev(); return updateDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; warnInvalidHookAccess(); updateHookTypesDev(); @@ -3118,7 +3118,7 @@ if (__DEV__) { updateHookTypesDev(); return rerenderDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; warnInvalidHookAccess(); updateHookTypesDev(); diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index b51d2020a8fad..50fe2d424b828 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -1728,27 +1728,27 @@ function startTransition(setPending, callback) { } } -function mountTransition(): [(() => void) => void, boolean] { +function mountTransition(): [boolean, (() => void) => void] { const [isPending, setPending] = mountState(false); // The `start` method never changes. const start = startTransition.bind(null, setPending); const hook = mountWorkInProgressHook(); hook.memoizedState = start; - return [start, isPending]; + return [isPending, start]; } -function updateTransition(): [(() => void) => void, boolean] { +function updateTransition(): [boolean, (() => void) => void] { const [isPending] = updateState(false); const hook = updateWorkInProgressHook(); const start = hook.memoizedState; - return [start, isPending]; + return [isPending, start]; } -function rerenderTransition(): [(() => void) => void, boolean] { +function rerenderTransition(): [boolean, (() => void) => void] { const [isPending] = rerenderState(false); const hook = updateWorkInProgressHook(); const start = hook.memoizedState; - return [start, isPending]; + return [isPending, start]; } let isUpdatingOpaqueValueInRenderPhase = false; @@ -2294,7 +2294,7 @@ if (__DEV__) { mountHookTypesDev(); return mountDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; mountHookTypesDev(); return mountTransition(); @@ -2424,7 +2424,7 @@ if (__DEV__) { updateHookTypesDev(); return mountDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; updateHookTypesDev(); return mountTransition(); @@ -2554,7 +2554,7 @@ if (__DEV__) { updateHookTypesDev(); return updateDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; updateHookTypesDev(); return updateTransition(); @@ -2685,7 +2685,7 @@ if (__DEV__) { updateHookTypesDev(); return rerenderDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; updateHookTypesDev(); return rerenderTransition(); @@ -2827,7 +2827,7 @@ if (__DEV__) { mountHookTypesDev(); return mountDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; warnInvalidHookAccess(); mountHookTypesDev(); @@ -2972,7 +2972,7 @@ if (__DEV__) { updateHookTypesDev(); return updateDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; warnInvalidHookAccess(); updateHookTypesDev(); @@ -3118,7 +3118,7 @@ if (__DEV__) { updateHookTypesDev(); return rerenderDeferredValue(value); }, - useTransition(): [(() => void) => void, boolean] { + useTransition(): [boolean, (() => void) => void] { currentHookNameInDev = 'useTransition'; warnInvalidHookAccess(); updateHookTypesDev(); diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index b1764bed5ac34..c0b0415e95705 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -313,7 +313,7 @@ export type Dispatcher = {| ): void, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void, useDeferredValue(value: T): T, - useTransition(): [(() => void) => void, boolean], + useTransition(): [boolean, (() => void) => void], useMutableSource( source: MutableSource, getSnapshot: MutableSourceGetSnapshotFn, diff --git a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js index bc37abbd322f4..ce9236e114b96 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js @@ -1511,7 +1511,7 @@ describe('ReactHooks', () => { ]; if (__EXPERIMENTAL__) { - const useTransitionHelper = () => React.useTransition({timeoutMs: 1000}); + const useTransitionHelper = () => React.useTransition(); const useDeferredValueHelper = () => React.useDeferredValue(0, {timeoutMs: 1000}); diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index cf4e4a3f3b619..3853862a7778b 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -832,7 +832,8 @@ describe('ReactHooksWithNoopRenderer', () => { let startTransition; function App() { const [counter, setCounter] = useState(0); - const [_startTransition] = useTransition(); + // eslint-disable-next-line no-unused-vars + const [_, _startTransition] = useTransition(); startTransition = _startTransition; if (counter === 0) { @@ -3140,9 +3141,7 @@ describe('ReactHooksWithNoopRenderer', () => { let transition; function App() { const [show, setShow] = useState(false); - const [startTransition, isPending] = useTransition({ - timeoutMs: 1000, - }); + const [isPending, startTransition] = useTransition(); transition = () => { startTransition(() => { setShow(true); diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js index d7da84e67b752..be82c514da48d 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js @@ -3526,7 +3526,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { let startTransition; function B() { const [textB, _setTextB] = useState('B'); - const [_startTransition] = useTransition({timeoutMs: 10000}); + // eslint-disable-next-line no-unused-vars + const [_, _startTransition] = useTransition(); startTransition = _startTransition; setTextB = _setTextB; return ( @@ -3624,12 +3625,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { let setTextWithLongTransition; function App() { - const [startShortTransition, isPending1] = React.unstable_useTransition({ - timeoutMs: 5000, - }); - const [startLongTransition, isPending2] = React.unstable_useTransition({ - timeoutMs: 30000, - }); + const [isPending1, startShortTransition] = React.unstable_useTransition(); + const [isPending2, startLongTransition] = React.unstable_useTransition(); const isPending = isPending1 || isPending2; const [text, setText] = React.useState(''); const [mirror, setMirror] = React.useState(''); diff --git a/packages/react-reconciler/src/__tests__/ReactTransition-test.js b/packages/react-reconciler/src/__tests__/ReactTransition-test.js index 09ba5dded7307..71c40cefebe8a 100644 --- a/packages/react-reconciler/src/__tests__/ReactTransition-test.js +++ b/packages/react-reconciler/src/__tests__/ReactTransition-test.js @@ -164,7 +164,7 @@ describe('ReactTransition', () => { let start; function App() { const [show, setShow] = useState(false); - const [_start, isPending] = useTransition(); + const [isPending, _start] = useTransition(); start = () => _start(() => setShow(true)); return ( }> @@ -208,7 +208,7 @@ describe('ReactTransition', () => { async () => { let update; function App() { - const [startContentChange, isContentPending] = useTransition(); + const [isContentPending, startContentChange] = useTransition(); const [label, setLabel] = useState('A'); const [contents, setContents] = useState('A'); update = value => { diff --git a/packages/react/src/ReactHooks.js b/packages/react/src/ReactHooks.js index d397d8f789f0a..e8d1682a12910 100644 --- a/packages/react/src/ReactHooks.js +++ b/packages/react/src/ReactHooks.js @@ -162,7 +162,7 @@ export function useDebugValue( export const emptyObject = {}; -export function useTransition(): [(() => void) => void, boolean] { +export function useTransition(): [boolean, (() => void) => void] { const dispatcher = resolveDispatcher(); return dispatcher.useTransition(); }