diff --git a/packages/core/package.json b/packages/core/package.json index 23667932..fe0a7cd5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -39,15 +39,13 @@ "escape-string-regexp": "^4.0.0", "nanoid": "^3.1.15", "query-string": "^6.13.6", - "react-is": "^16.13.0", - "use-subscription": "^1.5.0" + "react-is": "^16.13.0" }, "devDependencies": { "@react-native-community/bob": "^0.16.2", "@testing-library/react-native": "^7.1.0", "@types/react": "^16.9.53", "@types/react-is": "^16.7.1", - "@types/use-subscription": "^1.0.0", "del-cli": "^3.0.1", "react": "~16.13.1", "react-test-renderer": "~16.13.1", diff --git a/packages/core/src/useIsFocused.tsx b/packages/core/src/useIsFocused.tsx index bbdb0e70..a789fb75 100644 --- a/packages/core/src/useIsFocused.tsx +++ b/packages/core/src/useIsFocused.tsx @@ -1,32 +1,42 @@ import * as React from 'react'; -import { useSubscription } from 'use-subscription'; +import { useState } from 'react'; import useNavigation from './useNavigation'; /** * Hook to get the current focus state of the screen. Returns a `true` if screen is focused, otherwise `false`. * This can be used if a component needs to render something based on the focus state. - * It uses `use-subscription` under the hood for safer use in concurrent mode. */ export default function useIsFocused(): boolean { const navigation = useNavigation(); - // eslint-disable-next-line react-hooks/exhaustive-deps - const getCurrentValue = React.useCallback(navigation.isFocused, [navigation]); - const subscribe = React.useCallback( - (callback: () => void) => { - const unsubscribeFocus = navigation.addListener('focus', callback); + const [isFocused, setIsFocused] = useState(navigation.isFocused); - const unsubscribeBlur = navigation.addListener('blur', callback); + const valueToReturn = navigation.isFocused(); - return () => { - unsubscribeFocus(); - unsubscribeBlur(); - }; - }, - [navigation] - ); + if (isFocused !== valueToReturn) { + // If the value has changed since the last render, we need to update it. + // This could happen if we missed an update from the event listeners during re-render. + // React will process this update immediately, so the old subscription value won't be committed. + // It is still nice to avoid returning a mismatched value though, so let's override the return value. + // This is the same logic as in https://github.com/facebook/react/tree/master/packages/use-subscription + setIsFocused(valueToReturn); + } - return useSubscription({ - getCurrentValue, - subscribe, - }); + React.useEffect(() => { + const unsubscribeFocus = navigation.addListener('focus', () => + setIsFocused(true) + ); + + const unsubscribeBlur = navigation.addListener('blur', () => + setIsFocused(false) + ); + + return () => { + unsubscribeFocus(); + unsubscribeBlur(); + }; + }, [navigation]); + + React.useDebugValue(valueToReturn); + + return valueToReturn; } diff --git a/yarn.lock b/yarn.lock index d780fc76..f225fe15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4034,11 +4034,6 @@ dependencies: source-map "^0.6.1" -"@types/use-subscription@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/use-subscription/-/use-subscription-1.0.0.tgz#d146f8d834f70f50d48bd8246a481d096f11db19" - integrity sha512-0WWZ5GUDKMXUY/1zy4Ur5/zsC0s/B+JjXfHdkvx6JgDNZzZV5eW+KKhDqsTGyqX56uh99gwGwbsKbVwkcVIKQA== - "@types/wait-on@*": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/wait-on/-/wait-on-4.0.0.tgz#fb6fa2854b592f7344f1dd9836b5655795510dce" @@ -18740,7 +18735,7 @@ urlgrey@0.4.4: resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f" integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8= -use-subscription@^1.0.0, use-subscription@^1.5.0: +use-subscription@^1.0.0: version "1.5.0" resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.0.tgz#0df66fdf97b9a340147ad72f76fac1db6f56d240" integrity sha512-/FVRiB2I7NDjzWoNBYPt6YkkvleMm/lFtxj1hH6nX2TVrJ/5UTbovw9OE1efv2Zl0HoAYuTjM7zHd9OsABn5sg==