react-navigation / hooks Goto Github PK
View Code? Open in Web Editor NEWReact hooks for convenient react-navigation use
Home Page: https://reactnavigation.org
License: MIT License
React hooks for convenient react-navigation use
Home Page: https://reactnavigation.org
License: MIT License
function ReactComponent() {
const { navigate } = useNavigation();
useEffect(() => {
if (someBoolean) {
navigate(...)
}
}, [someBoolean,navigate])
}
The functions like navigate/goBack etc should be able to be used in hooks / dependency arrays.
We should rather make them stable so that they don't trigger effect re-execution on every navigate action, which is not the case currently (as reported by @cmmartin here: #3 (comment))
See also https://github.com/react-navigation/core/issues/71
The core does not provide stable action functions currently, and it may be complicated to do so and guarantee that as part of the core contract.
But we can provide stabilization in this package.
I've tried both approaches and end up with the same result:
// 1.
const { isFocused } = useNavigationFocus()
// 2.
const navigation = useNavigation();
const isFocused = navigation.isFocused();
This is in the context of a Tab Navigator. The first time I switch tab isFocused is updated - but after the initial render it doesn't update.
For now I went back to use withNavigationFocus
- I get a feeling this package needs some more testing before using! :)
如何在子页面里设置navigationOptions呢,我要动态控制tabBarLabel
Using react-navigation v4
Hook:
const navigation = useNavigation<any>();
Use hook:
navigation.popToTop();
Typescript error:
Property 'popToTop' does not exist on type 'NavigationScreenProp<any, NavigationParams>'.ts(2339)
A few tests should be able to cover this simple library. Most of this task is setting up jest properly, and the tests will be fairly easy to write
Suppose i have the following code, willBlur
event will not be triggered for ScreenTwo
.
const useCustomNavigationEventsHook = () => {
useNavigationEvents(evt => {
if(event === 'willFocus') {
alert("Will Focus");
} else if(event === 'willBlur') {
alert("Will Blur");
}
})
}
const ScreenOne = () => {
useCustomNavigationEventsHook();
// alert Will Focus
// Navigates to ScreenTwo
// alert Will Blur
}
const ScreenTwo = () => {
useCustomNavigationEventsHook();
// alert Will Focus will not be triggered here
}
However, if I move the navigation.addListener('willFocus')
outside of useEffect
like the following, it seems to be working fine for both screens.
const useNavigationEvents = handler => {
const subsWFRef = useRef(null);
if(!subsWFRef.current) {
subsWFRef.current = navigation.addListener('willFocus', handler);
}
useEffect(() => {
// This chunk is prob not necessary as we're already adding the listener synchronously above
if(!subsWFRef.current) {
subsWFRef.current = navigation.addListener('willFocus', handler);
}
// Other subscriptions
return () => {
subsWFRef.current.remove();
subsWFRef.current = null;
// Remove other subscriptions
}
},
// Existing deps
)
}
Is there an equivalent of goBack()?
Something similar to https://github.com/vonovak/react-navigation-backhandler with hooks
In addition to useNavigationEvents(handler)
, I propose two useNavigationEffect(handler)
hooks, that look and feel similar to the official react useEffect(handler)
:
useNavigationEffectInsideTransition(() => {
console.log('screen component did focus');
return function cleanup() {
console.log('screen component will blur');
};
});
and
useNavigationEffectOutsideTransition(() => {
console.log('screen component will focus');
return function cleanup() {
console.log('screen component did blur');
};
});
As with the useEffect(handler)
hook, the return of a cleanup function is optional.
To be honest the main problem is naming the two hooks to clarify if the effect is called inside the transitions or outside. Any alternative naming proposals are appreciated.
In my opinion these hooks would be much more intuitive, since people will be familiar with the useEffect(handler)
hook.
Are there any common use cases that require the combination of
willFocus
& willBlur
or didFocus
& didBlur
instead of
willFocus
& didBlur
or didFocus
& willBlur
?
What are your thoughts on this?
Ideally we would be providing the navigation state key to the useEffect hook, but it causes the events to be missed because re-subscription happens frequently.
See for context: https://github.com/react-navigation/react-navigation-hooks/blob/master/src/Hooks.js#L37-L42
Can somebody help investigate if we are doing the right thing here?
I haven't actually run hooks yet on RN because its quite complicated right now. This was developed on the web.
Could somebody test this on a RN app and see if anything funky happens?
Hello, I'm encountering following error during react-native run-android command.
error: bundling failed: Error: Unable to resolve module `tslib` from `PATH_TO_PROJECT/node_modules/react-navigation-hooks/dist/Hooks.js`: Module `tslib` does not exist in the Haste module map
This might be related to https://github.com/facebook/react-native/issues/4968
To resolve try the following:
1. Clear watchman watches: `watchman watch-del-all`.
2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
3. Reset Metro Bundler cache: `rm -rf /tmp/metro-bundler-cache-*` or `npm start -- --reset-cache`.
4. Remove haste cache: `rm -rf /tmp/haste-map-react-native-packager-*`.
at ModuleResolver.resolveDependency (PATH_TO_PROJECT/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:183:15)
at ResolutionRequest.resolveDependency (PATH_TO_PROJECT/node_modules/metro/src/node-haste/DependencyGraph/ResolutionRequest.js:52:18)
at DependencyGraph.resolveDependency (PATH_TO_PROJECT/node_modules/metro/src/node-haste/DependencyGraph.js:283:16)
at Object.resolve (PATH_TO_PROJECT/node_modules/metro/src/lib/transformHelpers.js:264:42)
at dependencies.map.result (PATH_TO_PROJECT/node_modules/metro/src/DeltaBundler/traverseDependencies.js:399:31)
at Array.map (<anonymous>)
at resolveDependencies (PATH_TO_PROJECT/node_modules/metro/src/DeltaBundler/traverseDependencies.js:396:18)
at PATH_TO_PROJECT/node_modules/metro/src/DeltaBundler/traverseDependencies.js:269:33
at Generator.next (<anonymous>)
at asyncGeneratorStep (PATH_TO_PROJECT/node_modules/metro/src/DeltaBundler/traverseDependencies.js:87:24)
I've tried commands from error message and I've also tried to remove package completely and reinstall it but nothing seems to be working.
react-native: 0.60.3
react-navigation-hooks: 1.0.1
Thanks!
I am trying to change my react-navigation to hooks and navigating to pages using navigate("Page") works for but openDrawer does not:
const { navigate } = useNavigation();
return (
<Button transparent onPress={() => navigate.openDrawer()}>
<Icon active name="menu"/>
</Button>
)
Is this a bug in react-navigation hooks or am I doing something wrong?
react-navigation-hooks 1.0.1
doing this in react-native using expo 34
Hi,
I just want to warn that this implementation is problematic:
export function useNavigationEvents(handleEvt) {
const navigation = useNavigation();
useEffect(
() => {
const subsA = navigation.addListener('action', handleEvt);
const subsWF = navigation.addListener('willFocus', handleEvt);
const subsDF = navigation.addListener('didFocus', handleEvt);
const subsWB = navigation.addListener('willBlur', handleEvt);
const subsDB = navigation.addListener('didBlur', handleEvt);
return () => {
subsA.remove();
subsWF.remove();
subsDF.remove();
subsWB.remove();
subsDB.remove();
};
},
// For TODO consideration: If the events are tied to the navigation object and the key
// identifies the nav object, then we should probably pass [navigation.state.key] here, to
// make sure react doesn't needlessly detach and re-attach this effect. In practice this
// seems to cause troubles
undefined
// [navigation.state.key]
);
}
The key is needed, otherwise the events will be removed/added on every update.
Unfortunately when you add a didFocus listener on a focused view, the listener will fire immediately after adding (async), which has lead to an infinite loop on this issue: react-navigation/react-navigation#5058
I suggest as a solution to:
I can try to provide an implementation if you want
I've noticed that for some reason navigationOptions aren't set correctly when using useEffect to initialize them when component mounts.
Here's a basic test scenario to reproduce this:
function TestScreen() {
const navigation = useNavigation();
useEffect(() => {
console.log('component did mount');
navigation.setParams({
test: true,
});
}, []);
return null;
}
TestScreen.navigationOptions = (screenProps) => {
console.log('navigationOptions', screenProps.navigation.state.params);
};
When this screen gets navigated to, here's what I see in logs:
navigationOptions undefined
component did mount
navigationOptions {test: true}
navigationOptions undefined
Shouldn't it be:
navigationOptions undefined
component did mount
navigationOptions {test: true}
I've also noticed that output is correct when I wrap navigation.setParams
in setTimeout
:
useEffect(() => {
setTimeout(() => {
navigation.setParams({
test: true,
});
}, 0);
}, []);
How to reset the navigation stack, example: Login Screen for Home.
Issue to discuss what should be included in v2, including breaking changes.
Keep in mind this project is temporary and v5 will ship with hooks directly in core.
The goal for v2 is to try to avoid introducing any new hook that won't be in v5, as it would only make the v3/v4 => v5 migration more painful.
I am currently using useFocusState to configure parts of my screens when the screen focuses or isFocusing. It does not get triggered if the user swipes back though.
Would it be an idea to import useNavigation
from `'@react-navigation/native';`` and use that if the user has react-navigation v5 installed? I'm in the process of upgrading from v4 to v5 and of course lots of my screens are broken.
It might be a silly idea?
I'm using react-navigation-hooks in react native and i'm getting this error when i use the useNavigation example:
TypeError: undefined is not an object (evaluating '_useNavigation.navigate')
this is mi code:
import {useNavigation} from 'react-navigation-hooks';
export default function renderItmFlat(props) {
const {navigate} = useNavigation();
return(
<TouchableOpacity
//disabled={this.state.blockBtn?true:false}
style={{flex: 1,
flexDirection: 'row',
paddingLeft: 15,
paddingVertical: 30,
borderRightColor: '#D7D7D7',
borderRightWidth: 0.5,
alignItems: 'center'}}
//onPress={onStartPress}
onPress={() => navigate('Store')}
>
could you help me please?
These hooks don't seem to work on the web. I'm trying to run this react-navigation web example but with latest versions. Between 1.0.0-alpha2
and 1.1.0
hooks now directly imports from react-navigation
instead of relying on @react-navigation/core
. So running the example with latest versions of hooks results in an error (below) even though it is listed only as a devDepdendency. If you then add react-navigation
you'll of course end up with all the react-native stuff.
I'd like to use react-navigation and hooks on the web but it seems impossible. Our common code features many hooks that rely on this but I'm thinking react-router might be a safer choice for now.
Cannot find module 'react-navigation'
Require stack:
- /Users/aforty/Code/web-server-example/node_modules/react-navigation-hooks/dist/commonjs/Hooks.js
- /Users/aforty/Code/web-server-example/build/server.js
$ yarn add react-navigation
...
success Saved 5 new dependencies.
info Direct dependencies
└─ [email protected]
info All dependencies
├─ @react-navigation/[email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
└─ [email protected]
How do you use setTopLevelNavigator which is available in react-navigation?
I'm shallow rendering a component that uses useNavigationParam
and getting TypeError: Cannot read property 'getParam' of undefined
. Is there a recommended way to provide NavigationContext for testing (I'm using Jest)? I used to just pass a fake navigation
prop but that won't be passed to NavigationContext.
I'd expect that underneath defaultHandler()
function in navigationOptions > tabBarOnPress
of bottom tab navigator, it runs navigate
function (I may be wrong), but great addition would be to pass some params for those tabs; for example:
const MyNavigator = createBottomTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: () => ({
tabBarOnPress: ({ navigation, defaultHandler }) => {
defaultHandler({ foo: 'bar' });
},
}),
},
},
);
function App(){
const navigation = useNavigation()
<Stack.Navigator
screenOptions={{
headerStyle: { backgroundColor: '#5F27CD' },
headerTintColor: '#fff',
headerBackTitleVisible: false,
headerLeftContainerStyle: { marginLeft: 17 },
}}
initialRouteName='Tabs'
>
<Stack.Screen
name='somename'
component={somepage}
options={{
title: 'sometitle',
headerLeft: () => (
<TouchableOpacity onPress={() => {navigation.navigate('somepage')}}>
),
}}
/>
</Stack.Navigator
}
Return me this error:
Error: Couldn't find a navigation object. Is your component inside a screen in a navigator?
This error is located at:
in AppRoutes (at routes.tsx:112)
in Routes (at App.tsx:149)
in EnsureSingleNavigator (at BaseNavigationContainer.tsx:268)
in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:39)
in ThemeProvider (at NavigationContainer.tsx:38)
in ForwardRef(NavigationContainer) (at App.tsx:147)
in BgTracking (at renderApplication.js:40)
in RCTView (at AppContainer.js:101)
in RCTView (at AppContainer.js:119)
in AppContainer (at renderApplication.js:39)
useNavigation
useNavigation.tsx:18:6
AppRoutes
routes.tsx:42:21
renderRoot
[native code]:0
runRootCallback
[native code]:0
forEach
[native code]:0
Refresh.performReactRefresh
setUpReactRefresh.js:43:6
setTimeout$argument_0
require.js:609:10
callFunctionReturnFlushedQueue
[native code]:0
Hi when I do:
const {index} = useNavigationState()
to get the current page index the page index is always undefined
Related to #33
We'd rather fail fast if context is not found and user use useNavigation()
, with an option to allow useNavigation to return undefined, to support more advanced usecases (see the PR)
This generates a loop when is used on useEffect
const { setParams } = useNavigation();
const { error, data, refetch } = Apollo.useQuery<GetCardsResponse>(GET_CARDS);
useEffect(() => {
if (data) {
setParams({ showTitle: data.cards.length > 0 });
}
}, [data, setParams]);
Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
This works:
useEffect(() => {
if (data) {
setParams({ showTitle: data.cards.length > 0 });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data]);
Is it too late to suggest a change in the interface for useNavigationParam
?
I'm working on some code and found myself using the navigation param as the only state for a scene of mine. The idea is that you pass in a value and a callback function as navigation params to a modal scene, which lets you edit said value and eventually accept it (which triggers the callback) or cancel (which just triggers goBack
for now, but might as well call another callback if defined).
so I found myself writing something like
const value = navigation.getParam('value', '');
const setValue = (newValue) => { navigation.setParams({ value: newValue }); };
and using it much like I'd use useState
.
So, thinking "this would be a useful abstraction on top of a useNavigation
hook", I found this repo. I was thinking an interface like this for useNavigationParam
might make sense, where you can either destruct out only the value, or get both the value and a setter function to update it. So I figured I might as well create an issue with this suggestion, and see what others think. :)
Reported by in https://github.com/react-navigation/hooks/pull/43/files#r334335721 by @ArrayZoneYour
The following code is likely to produce an infinite loop, even if we make sure the dependency is stable using a ref, because useFocusEffect use "navigation" as a dependency and the object is unstable.
useFocusEffect(useCallback(() => {
setParamsRef.current({});
},[setParamsRef]));
The focus effect might retrigger unnecessarily due to the navigation being unstable
Somehow this is related to #40
@satya164 what do you think about using a useNavigationRef
hook as you suggested in some other issue? Didn't get a clear answer from the React team on how to handle this kind of situation but that should work. Or maybe I should depend only on isFocused
and addListener
which are the only 2 fn used, but if core does not guarantee stability across render the problem remains.
@bySabi, is there any way we can remove react-navigation-types-only
, and use something more permanent instead?
Ideally we would be using @types/react-navigation or something similar, but I understand that can be tricky because we really just want the types in core.
cc @horacioh, can you provide some guidance on cleaning this up?
how can I open&close the Drawer Navigator using hooks?
const { setParams } = useNavigation();
useEffect(() => {
setParams({ myParam: 'myValue' });
}, [setParams]);
causes Invariant Violation: Maximum update depth exceeded
. And when using best practices according to eslint-plugin-react-hooks
this dependency is automatically added. I suggest:
eslint-plugin-react-hooks
works, but would of course be great if it wouldn't include something like setParams automatically. For setState this is the case - maybe using setState under the hood would make it smarter? Otherwise it's probably outside the scope of this package! :)I have created the following issue regarding useNavigation
error : https://github.com/react-navigation/native/issues/37
Should I instead use this module? If yes, I am currently implementing react-navigation 4.0.10, while you seems to support 3.11.1 (See https://github.com/react-navigation/hooks/blob/master/package.json#L62)
Which packages should I use to access the navigation
object?
There is a way to define navigation params typing on useNavigation with typescript ?
const navigation = useNavigation<{ params: { title: string } }>();
const title = navigation.getParam("title"); // title is inferred as "any" not "string"...
This is not working useNavigation because of this (P default value/type) :
export interface NavigationScreenProp<S, P = NavigationParams> {
state: S & { params?: P };
...
there is no access to optional second type on NavigationScreenProp...
useFocusEffect
will be called on Drawer everytime the app navigates to another route
I've fixed like this:
useEffect(() => {
if (navigation.state.isDrawerOpen) {
// handle navigation is open
}
}, [navigation.state?.isDrawerOpen]);
getParam
provides a default as a second paramter to the function in case the requested param is null. useNavigationParam
should provide that same behavior.
If I extract 'navigation' from props, everything is fine. However, if I decide to utilize useNavigation() which is part of react-navigation-hooks, I get this warning:
can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks...
Could be something is wrong with my useEffect hook?
import React, {useEffect} from 'react';
import {View, ActivityIndicator} from 'react-native';
import {isSignedIn} from './isSignedIn';
import {useNavigation} from 'react-navigation-hooks';
export const CustomAuthenticator: React.FC = () => {
const [user, setUser] = React.useState(false);
useEffect(() => {
const res = async () => {
const u = await isSignedIn();
setUser(u);
};
return res;
}, [user]);
const {navigate} = useNavigation();
return (
<View>
<ActivityIndicator>{navigate(user ? 'App' : 'Auth')}</ActivityIndicator>
</View>
);
};
Can I reproduce events like "onEnter/onExit" ?
OnEnter -> transition enter finish
OnExit -> transition exit finish
thanks
This is a huge one..
We might be able to use hooks to build a navigationOptions API that is dramatically more convenient for people than our current options
I'm open to ideas on this one and I'm curious what people like @satya164 think
Question:
Whats the proper way to use this library with storybooks? I currently get an error that it expects a navigation context. It would make sense to have something like https://github.com/abhiaiyer91/apollo-storybook-decorator but for react-navigation.
What are poeple doing in the meantime?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.