From 66f3a4a0bb39475434668bc94fb1750dbe618ee0 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 4 Nov 2020 12:57:49 +0100 Subject: [PATCH] fix: don't use use-subscription to avoid peer dep related errors The `use-subscription` package has a peer dep on latest React. This is problematic when using npm due to it's peer dependency algorithm which installs multiple versions of React when using an older version of React (Native). This means that we'll need to use an ancient version of `use-subscription` to support older React versions with npm and make sure to never update it, or test with every version. It's much lower maintenance to incporporate the same update in render logic that `use-subscription` has and not deal with dependencies. So this commit removes the `use-subscription` dependency. See https://github.com/react-navigation/react-navigation/issues/9021#issuecomment-721679760 for more context. --- packages/core/package.json | 4 +-- packages/core/src/useIsFocused.tsx | 48 ++++++++++++++++++------------ yarn.lock | 7 +---- 3 files changed, 31 insertions(+), 28 deletions(-) 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==