Mobx + React Native 獲取路由的狀態信息

年前公司由一個項目是使用 ReactNative 來開發的因此遇到了一些問題,比較影響開發進程的就是路由問題了,實際上就是 ReactNavigation 這個組件比較難懂,這裏給你們講解一下,但願你們少踩點坑.另外本篇文章使用的是 TypeScript環境react

主要講解的仍是 如何使用Mobx記錄ReactNative中路由的狀態 可是會穿插一些小內容,這裏雖然講到的是 Mobx , 若是你使用的是 redux 的話也不用灰心,原理都是同樣的,只要能看懂這篇文章,那我相信對於 ReactNavigation 有了更深的瞭解redux

ReactNavigation的官網上面有 redux的教程

API介紹

在開發以前我先向你們介紹一下須要使用到的APIide

  • NavigationActions
  • getStateForAction
  • addNavigationHelpers

NavigationActions裏面存在了不少方法,在這裏我先講 NavigationActions.init(), 其實是用來獲取 初始狀態 的路由信息,固然你也能夠不使用這個API,來本身手動寫出初始的路由狀態,可是我不太推薦這個方法,第一個是路由擴展的時候你又要去從新改,第二個是ReactNavigation這個庫的改動很頻繁,說不定哪一天就變了個格式,到時候你又要重寫this

getStateForAction(action, state) 提供一個 action上一次的路由狀態 從而獲取最新的路由狀態spa

addNavigationHelpers(navigation) 是記錄路由狀態的核心方法,如何理解呢?咱們看到他的參數是 navigation 這是一個對象,咱們這裏只講其中的兩個值 statedispatch,這裏的 dispatchreduxdispatch 的概念是類似的,在 ReactNavigation 裏面每次路由的改變,他都會在裏面觸發 dispatch 而且傳遞一個 action,有了action以後能夠經過getStateForAction來獲取當前路由的state.state則是保證當前創建的路由信息和Mobx保存的路由信息的一致性code

實現代碼

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 都不是問題router

另一些小問題

在開發 ReactNative 的時候可能在某個頁面須要跳轉,這個時候你不得不把 navigation 從頭傳到底,這種體驗很糟糕我更推薦使用一些 API快速跳轉 或者 傳遞參數server

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 文檔,剛剛上去又看了一下發現有些改動,我研究下有沒有須要改動的地方,不過大體看了下,應該沒啥變化

參考資料:對象

相關文章
相關標籤/搜索