1 | import * as React from 'react';
|
2 | import {
|
3 | getStateFromPath,
|
4 | getActionFromState,
|
5 | NavigationContext,
|
6 | } from '@react-navigation/core';
|
7 | import LinkingContext from './LinkingContext';
|
8 |
|
9 | export default function useLinkTo() {
|
10 | const navigation = React.useContext(NavigationContext);
|
11 | const linking = React.useContext(LinkingContext);
|
12 |
|
13 | const linkTo = React.useCallback(
|
14 | (path: string) => {
|
15 | if (!path.startsWith('/')) {
|
16 | throw new Error(`The path must start with '/' (${path}).`);
|
17 | }
|
18 |
|
19 | if (navigation === undefined) {
|
20 | throw new Error(
|
21 | "Couldn't find a navigation object. Is your component inside a screen in a navigator?"
|
22 | );
|
23 | }
|
24 |
|
25 | const { options } = linking;
|
26 |
|
27 | const state = options?.getStateFromPath
|
28 | ? options.getStateFromPath(path, options.config)
|
29 | : getStateFromPath(path, options?.config);
|
30 |
|
31 | if (state) {
|
32 | let root = navigation;
|
33 | let current;
|
34 |
|
35 |
|
36 | while ((current = root.dangerouslyGetParent())) {
|
37 | root = current;
|
38 | }
|
39 |
|
40 | const action = getActionFromState(state, options?.config);
|
41 |
|
42 | if (action !== undefined) {
|
43 | root.dispatch(action);
|
44 | } else {
|
45 | root.reset(state);
|
46 | }
|
47 | } else {
|
48 | throw new Error('Failed to parse the path to a navigation state.');
|
49 | }
|
50 | },
|
51 | [linking, navigation]
|
52 | );
|
53 |
|
54 | return linkTo;
|
55 | }
|