Skip to content
This repository was archived by the owner on May 20, 2021. It is now read-only.

Commit fde209f

Browse files
committed
Add link component utility
1 parent d8456a2 commit fde209f

3 files changed

Lines changed: 77 additions & 0 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
},
6868
"peerDependencies": {
6969
"react": "*",
70+
"react-dom": "*",
7071
"@react-navigation/core": "^3.0.0-alpha.8"
7172
},
7273
"jest": {

src/Link.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React, { Component } from 'react';
2+
import { withNavigation, NavigationActions } from '@react-navigation/core';
3+
4+
const queryString = require('query-string');
5+
6+
const getTopNavigation = navigation => {
7+
const parent = navigation.dangerouslyGetParent();
8+
if (parent) {
9+
return getTopNavigation(parent);
10+
}
11+
return navigation;
12+
};
13+
14+
class LinkWithNavigation extends Component {
15+
render() {
16+
const {
17+
children,
18+
params,
19+
routeName,
20+
routeKey,
21+
navigation,
22+
action,
23+
} = this.props;
24+
const topNavigation = getTopNavigation(navigation);
25+
const topRouter = topNavigation.router;
26+
const navAction =
27+
action ||
28+
NavigationActions.navigate({
29+
routeName,
30+
key: routeKey,
31+
params,
32+
});
33+
if (!action && !routeName && !routeKey) {
34+
throw new Error(
35+
'Must provide a routeName, routeKey, or a navigation action prop to <Link>'
36+
);
37+
}
38+
if (action && routeKey) {
39+
throw new Error(
40+
'Cannot specify a conflicting "routeKey" and a navigation "action" prop. Either use routeName with routeKey to specify a navigate action, or provide the specific navigation "action" prop.'
41+
);
42+
}
43+
if (action && routeName) {
44+
throw new Error(
45+
'Cannot specify a conflicting "routeName" and a navigation "action" prop. Either use routeName with routeKey to specify a navigate action, or provide the specific navigation "action" prop.'
46+
);
47+
}
48+
const navActionResponse = topRouter.getStateForAction(
49+
navAction,
50+
topNavigation.state
51+
);
52+
const nextState =
53+
navActionResponse === null ? topNavigation.state : navActionResponse;
54+
const pathAndParams = topRouter.getPathAndParamsForState(nextState);
55+
const href = Object.keys(pathAndParams.params).length
56+
? `/${pathAndParams.path}?${queryString.stringify(pathAndParams.params)}`
57+
: `/${pathAndParams.path}`;
58+
return (
59+
<a
60+
href={href}
61+
onClick={e => {
62+
navigation.dispatch(navAction);
63+
e.preventDefault();
64+
}}
65+
>
66+
{children}
67+
</a>
68+
);
69+
}
70+
}
71+
const Link = withNavigation(LinkWithNavigation);
72+
73+
export default Link;

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@ module.exports = {
55
get handleServerRequest() {
66
return require('./handleServerRequest').default;
77
},
8+
get Link() {
9+
return require('./Link').default;
10+
},
811
};

0 commit comments

Comments
 (0)