年前公司由一个项目是使用 ReactNative
来开发的所以遇到了一些问题,比较影响开发进程的就是路由问题了,实际上就是 ReactNavigation
这个组件比较难懂,这里给大家讲解一下,希望大家少踩点坑.另外本篇文章使用的是 TypeScript
环境
主要讲解的还是 如何使用Mobx记录ReactNative中路由的状态
但是会穿插一些小内容,这里虽然讲到的是 Mobx
, 如果你使用的是 redux
的话也不用灰心,原理都是一样的,只要能看懂这篇文章,那我相信对于 ReactNavigation
有了更深的了解
ReactNavigation
的官网上面有redux
的教程
API介绍
在开发之前我先向大家介绍一下需要使用到的API
- NavigationActions
- getStateForAction
- addNavigationHelpers
NavigationActions
里面存在了很多方法,在这里我先讲 NavigationActions.init()
, 实际上是用来获取 初始状态
的路由信息,当然你也可以不使用这个API,来自己手动写出初始的路由状态,但是我不太推荐这个方法,第一个是路由扩展的时候你又要去重新改,第二个是ReactNavigation
这个库的改动很频繁,说不定哪一天就变了个格式,到时候你又要重写
getStateForAction(action, state)
提供一个 action
和 上一次的路由状态
从而获取最新的路由状态
addNavigationHelpers(navigation)
是记录路由状态的核心方法,如何理解呢?我们看到他的参数是 navigation
这是一个对象,我们这里只讲其中的两个值 state
和 dispatch
,这里的 dispatch
和 redux
的dispatch
的概念是相似的,在 ReactNavigation
里面每次路由的改变,他都会在里面触发 dispatch
并且传递一个 action
,有了action
之后可以通过getStateForAction
来获取当前路由的state
.state
则是保证当前建立的路由信息和Mobx
保存的路由信息的一致性
实现代码
import * as React from "react";
import * as stores from "@stores";
import Router from "./router";// 自己定义的路由结构
import { Provider } from "mobx-react/native";
import { addNavigationHelpers } from "react-navigation";
import { observer } from "mobx-react";
import { useStrict } from "mobx";
useStrict(true);
console.disableYellowBox = true;
interface Props {}
interface State {}
@observer
export default class App extends React.Component<Props, State> {
constructor(props, context) {
super(props, context);
}
render() {
let { nav } = stores;
return (
<Provider {...stores}>
<Router
navigation={addNavigationHelpers({
dispatch: nav.dispatch.bind(nav),
state: nav.navigatorState
})}
/>
</Provider>
);
}
}
// store
import { observable, action, computed } from "mobx";
import { NavigationActions, NavigationState } from "react-navigation";
import RootRouter from "@router/index"; // 自己定义的路由结构
export class NavStore {
@observable.ref navigatorState: NavigationState;
constructor() {
this.navigatorState = RootRouter.router.getStateForAction(
NavigationActions.init(),
null
);
}
// 提供一个获取当前路由层级的功能
private getRouterName(state) {
let childRouters = state.routes;
if (childRouters && childRouters.length > 0) {
let curRouterName = childRouters[state.index].routeName;
let nextRouterName = this.getRouterName(childRouters[state.index]);
let result = nextRouterName ? "-" + nextRouterName : "";
return curRouterName + result;
}
return "";
}
@computed
get routerName() {
return this.getRouterName(this.navigatorState);
}
@action
dispatch(action) {
const previousNavState = this.navigatorState;
return (this.navigatorState = RootRouter.router.getStateForAction(
action,
previousNavState
));
}
}
export default new NavStore();
大家对 Mobx
不熟悉的话其实看我前面API的介绍就好了,核心就是addNavigationHelpers
提供了覆盖 dispatch
和 同步state
的功能,只要理解了这个,无论你使用 redux
还是 Mobx
都不是问题
另外一些小问题
在开发 ReactNative
的时候可能在某个页面需要跳转,这个时候你不得不把 navigation
从头传到底,这种体验很糟糕我更推荐使用一些 API
去 快速跳转
或者 传递参数
import { NavigationActions } from "react-navigation";
// 使用我上面定义的dispatch
// 简单跳转
dispatch(
NavigationActions.navigate({ routeName: "Search" })
);
// 带参数跳转
dispatch(
NavigationActions.navigate({
routeName: "Search" ,
params : { name : "Jason "}
})
)
// 多级跳转
dispatch(
NavigationActions.navigate({
routeName: "Search",
action : NavigationActions.navigate({ routeName: "User" })
})
);
这篇文章是年前的 ReactNavigation
文档,刚刚上去又看了一下发现有些改动,我研究下有没有需要改动的地方,不过大致看了下,应该没啥变化
参考资料:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。