mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-29 21:05:29 +08:00
feat: support navigate-like object in Link
This commit is contained in:
@@ -2,9 +2,10 @@ import * as React from 'react';
|
||||
import { Text, TextProps, GestureResponderEvent, Platform } from 'react-native';
|
||||
import type { NavigationAction } from '@react-navigation/core';
|
||||
import useLinkProps from './useLinkProps';
|
||||
import type { To } from './useLinkTo';
|
||||
|
||||
type Props = {
|
||||
to: string;
|
||||
to: To;
|
||||
action?: NavigationAction;
|
||||
target?: string;
|
||||
onPress?: (
|
||||
|
||||
@@ -4,10 +4,10 @@ import {
|
||||
NavigationAction,
|
||||
NavigationHelpersContext,
|
||||
} from '@react-navigation/core';
|
||||
import useLinkTo from './useLinkTo';
|
||||
import useLinkTo, { To } from './useLinkTo';
|
||||
|
||||
type Props = {
|
||||
to: string;
|
||||
to: To;
|
||||
action?: NavigationAction;
|
||||
};
|
||||
|
||||
@@ -49,14 +49,6 @@ export default function useLinkProps({ to, action }: Props) {
|
||||
throw new Error("Couldn't find a navigation object.");
|
||||
}
|
||||
} else {
|
||||
if (typeof to !== 'string') {
|
||||
throw new Error(
|
||||
`To 'to' option is invalid (found '${String(
|
||||
to
|
||||
)}'. It must be a valid string for navigation.`
|
||||
);
|
||||
}
|
||||
|
||||
linkTo(to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,37 +6,57 @@ import {
|
||||
} from '@react-navigation/core';
|
||||
import LinkingContext from './LinkingContext';
|
||||
|
||||
export type To<
|
||||
ParamList extends ReactNavigation.RootParamList = ReactNavigation.RootParamList,
|
||||
RouteName extends keyof ParamList = keyof ParamList
|
||||
> =
|
||||
| string
|
||||
| (undefined extends ParamList[RouteName]
|
||||
? {
|
||||
screen: RouteName;
|
||||
params?: ParamList[RouteName];
|
||||
}
|
||||
: {
|
||||
screen: RouteName;
|
||||
params: ParamList[RouteName];
|
||||
});
|
||||
|
||||
export default function useLinkTo() {
|
||||
const navigation = React.useContext(NavigationContext);
|
||||
const linking = React.useContext(LinkingContext);
|
||||
|
||||
const linkTo = React.useCallback(
|
||||
(path: string) => {
|
||||
if (!path.startsWith('/')) {
|
||||
throw new Error(`The path must start with '/' (${path}).`);
|
||||
}
|
||||
|
||||
(to: To) => {
|
||||
if (navigation === undefined) {
|
||||
throw new Error(
|
||||
"Couldn't find a navigation object. Is your component inside a screen in a navigator?"
|
||||
);
|
||||
}
|
||||
|
||||
let root = navigation;
|
||||
let current;
|
||||
|
||||
// Traverse up to get the root navigation
|
||||
while ((current = root.getParent())) {
|
||||
root = current;
|
||||
}
|
||||
|
||||
if (typeof to !== 'string') {
|
||||
root.navigate(to.screen, to.params);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!to.startsWith('/')) {
|
||||
throw new Error(`The path must start with '/' (${to}).`);
|
||||
}
|
||||
|
||||
const { options } = linking;
|
||||
|
||||
const state = options?.getStateFromPath
|
||||
? options.getStateFromPath(path, options.config)
|
||||
: getStateFromPath(path, options?.config);
|
||||
? options.getStateFromPath(to, options.config)
|
||||
: getStateFromPath(to, options?.config);
|
||||
|
||||
if (state) {
|
||||
let root = navigation;
|
||||
let current;
|
||||
|
||||
// Traverse up to get the root navigation
|
||||
while ((current = root.getParent())) {
|
||||
root = current;
|
||||
}
|
||||
|
||||
const action = getActionFromState(state, options?.config);
|
||||
|
||||
if (action !== undefined) {
|
||||
|
||||
Reference in New Issue
Block a user