Skip to content

Commit d9f0d49

Browse files
author
徐远翔
committed
feat: Work with HOC: withRouter.
1 parent 92bd642 commit d9f0d49

File tree

8 files changed

+102
-31
lines changed

8 files changed

+102
-31
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
"scripts": {
55
"bootstrap": "lerna bootstrap",
66
"clean": "rimraf packages/*/lib",
7+
"lint": "eslint packages/*/src/**/*.{ts,tsx}",
78
"build": "cross-env NODE_ENV=production lerna run build",
8-
"watch": "cross-env NODE_ENV=development lerna run watch --parallel --concurrency 5",
9+
"watch": "cross-env NODE_ENV=development lerna run watch --parallel --concurrency 4",
910
"test": "cross-env NODE_ENV=test jest --coverage",
1011
"changelog": "node scripts/changelog",
1112
"prerelease": "yarn build",

packages/umi-preset-react-navigation/README.md

+36
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,42 @@ function Index() {
258258

259259
使用**命令式**跳转页面时,只能使用`history`的 API,**umi-preset-react-navigation**目前还不支持使用[react-navigation](https://reactnavigation.org/)提供的`navigation`来跳转,只能做导航条设置之类的操作。
260260

261+
## 页面间传递/接收参数
262+
263+
`IndexPage`点击`Link`,携带`query`参数路由到`HomePage`:
264+
265+
```jsx
266+
import React from 'react';
267+
import { Link } from 'umi';
268+
import { List } from '@ant-design/react-native';
269+
270+
const Item = List.Item;
271+
272+
export default function IndexPage() {
273+
return (
274+
<List>
275+
<Link to="/home?name=bar" component={Item} arrow="horizontal">
276+
主页
277+
</Link>
278+
</List>
279+
);
280+
}
281+
```
282+
283+
```jsx
284+
export default function HomePage({ route }) {
285+
console.log(route); // route 属性字段查看下面
286+
287+
// ...
288+
}
289+
```
290+
291+
`route`属性示例:
292+
293+
```json
294+
{ "key": "/home-WnnfQomYXFls0kS0v0lxo", "name": "/home", "params": { "name": "bar" } }
295+
```
296+
261297
## DeepLink
262298

263299
> 什么是 DeepLink ?

packages/umi-preset-react-navigation/package.json

-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@
4242
"umi": "^3.0.0"
4343
},
4444
"dependencies": {
45-
"@react-navigation/native": "5.3.0",
46-
"@react-navigation/stack": "5.3.3",
4745
"umi-renderer-react-navigation": "^0.1.0-alpha.2"
4846
}
4947
}

packages/umi-preset-react-navigation/src/plugins/features/reactNavigation.ts

+34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { IApi } from 'umi';
2+
import { dirname } from 'path';
23

34
export default (api: IApi) => {
5+
const {
6+
utils: { resolve, winPath },
7+
paths,
8+
} = api;
49
api.describe({
510
key: 'reactNavigation',
611
config: {
@@ -37,4 +42,33 @@ export default (api: IApi) => {
3742
},
3843
},
3944
});
45+
46+
/**
47+
* 这些依赖包含原生代码,必须安装到用户工程本地,不能由插件内置。
48+
* 原因:
49+
* 1. 似乎在用户工程 package.json 的 dependencies 字段中,RN 0.60.x 的自动链接才能生效;
50+
* 2. 比如如果存在两份 react-native-screens,会重复注册 Native Module,导致运行错误。
51+
*/
52+
const libs = [
53+
'@react-native-community/masked-view',
54+
'react-native-gesture-handler',
55+
'react-native-reanimated',
56+
'react-native-safe-area-context',
57+
'react-native-screens',
58+
];
59+
60+
/**
61+
* react-navigation 运行时 需要引入这些依赖
62+
* 必须将这些依赖库通过 alias 映射到 用户工程 node_modules 下的路径才能加载到
63+
*/
64+
api.chainWebpack((memo) => {
65+
libs.forEach((name) => {
66+
memo.resolve.alias.set(
67+
name,
68+
// RN 使用 Haste Module,专门针对 RN 的 依赖库 通常使用 CommonJS Module 的方式都没法获取到入口文件
69+
winPath(dirname(resolve.sync(`${name}/package.json`, { basedir: paths.absSrcPath }))),
70+
);
71+
});
72+
return memo;
73+
});
4074
};

packages/umi-preset-react-navigation/src/plugins/generateFiles/react-navigation/exports.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { IApi } from 'umi';
2+
import { dirname } from 'path';
23

3-
const CONTENT = `export {
4+
const TEMPLATE = `export {
45
useNavigation,
56
useRoute as useScreen,
67
useFocusEffect,
@@ -13,21 +14,20 @@ const CONTENT = `export {
1314
useScrollToTop,
1415
CommonActions,
1516
StackActions,
16-
} from '@react-navigation/native';
17-
export {
18-
SafeAreaProvider,
19-
SafeAreaView,
20-
useSafeAreaInsets,
21-
useSafeAreaFrame,
22-
} from 'react-native-safe-area-context';
17+
} from '{{{ reactNavigationPath }}}';
2318
2419
`;
2520

2621
export default (api: IApi) => {
22+
const {
23+
utils: { Mustache, winPath },
24+
} = api;
2725
api.onGenerateFiles(() => {
2826
api.writeTmpFile({
2927
path: 'react-navigation/exports.ts',
30-
content: CONTENT,
28+
content: Mustache.render(TEMPLATE, {
29+
reactNavigationPath: winPath(dirname(require.resolve('@react-navigation/native/package.json'))),
30+
}),
3131
});
3232
});
3333

packages/umi-preset-react-navigation/src/plugins/generateFiles/react-navigation/runtime.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import { IApi } from 'umi';
22
import { dirname, join } from 'path';
33
import runtimeTpl from './runtimeTpl';
4-
import { dependencies } from '../../../../package.json';
54

65
export default (api: IApi) => {
76
const {
87
utils: { Mustache, winPath },
98
} = api;
109

11-
api.addProjectFirstLibraries(() =>
12-
Object.keys(dependencies).map((name) => ({
13-
name,
14-
path: winPath(dirname(require.resolve(`${name}/package.json`))),
15-
})),
16-
);
17-
api.addEntryImportsAhead(() => [{ source: 'react-native-gesture-handler' }]);
10+
api.addEntryImportsAhead(() => [
11+
{
12+
source: 'react-native-gesture-handler',
13+
},
14+
]);
1815
api.addEntryImports(() => [
1916
{
2017
specifier: '{enableScreens}',
@@ -36,6 +33,8 @@ export default (api: IApi) => {
3633
api.writeTmpFile({
3734
path: 'react-navigation/runtime.tsx',
3835
content: Mustache.render(runtimeTpl, {
36+
rendererPath: winPath(dirname(require.resolve('umi-renderer-react-navigation/package.json'))),
37+
reactNavigationPath: winPath(dirname(require.resolve('@react-navigation/native/package.json'))),
3938
loading:
4039
typeof dynamicImport === 'object' && typeof dynamicImport.loading === 'string'
4140
? `require('${dynamicImport.loading}').default`

packages/umi-preset-react-navigation/src/plugins/generateFiles/react-navigation/runtimeTpl.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
export default `import React from 'react';
22
{{^loading}}import {View, Text} from 'react-native';{{/loading}}
33
import {ApplyPluginsType, dynamic} from 'umi';
4-
import {NavigationContainer, NavigationState} from '@react-navigation/native';
5-
import {Navigation} from 'umi-renderer-react-navigation';
4+
import {Navigation} from '{{{ rendererPath }}}';
5+
import {NavigationContainer} from '{{{ reactNavigationPath }}}';
66
77
export function rootContainer(container, {plugin, routes, history}) {
88
return React.createElement(
@@ -34,7 +34,7 @@ export function rootContainer(container, {plugin, routes, history}) {
3434
{
3535
theme: {{{ theme }}},
3636
initialState,
37-
onStateChange: (state?: NavigationState): void => {
37+
onStateChange: (state: any): void => {
3838
plugin.applyPlugins({
3939
key: 'onReactNavigationStateChange',
4040
type: ApplyPluginsType.event,

packages/umi-renderer-react-navigation/src/Navigation.tsx

+11-8
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,22 @@ export function Navigation(props: INavigationProps) {
109109
<Navigator initialRouteName="/" history={history}>
110110
{screens.map(({ key, component: Component, options: { routeMatchOpts, title, ...options }, ...rest }, idx) => (
111111
<Screen {...rest} key={key || `screen_${idx}`} options={{ ...options, title: title || defaultTitle }}>
112-
{({ route: screen, ...props }) => {
113-
const match = matchPath(history.location.pathname, routeMatchOpts) || context.match;
112+
{(props) => {
114113
const newProps = {
115114
...rests,
116115
...extraProps,
117-
history,
118-
location: history.location,
119-
route: routeMatchOpts,
120-
match,
121-
screen, // 避免和 umi 约定注入的 route 命名冲突,这里将 react-navigation 注入的 route 更换为 screen。
122116
...props,
123117
};
124-
return <Component {...newProps} />;
118+
return (
119+
<RouterContext.Provider
120+
value={{
121+
...context,
122+
match: matchPath(history.location.pathname, routeMatchOpts) || context.match,
123+
}}
124+
>
125+
<Component {...newProps} />
126+
</RouterContext.Provider>
127+
);
125128
}}
126129
</Screen>
127130
))}

0 commit comments

Comments
 (0)