react-navigation的多次點擊重復跳轉同一頁面、不在堆棧路由頁面使用navigation方法的解決思路
一、react-navigation的初使用
createStackNavigator ==> createSwitchNavigator ==> createAppContainer
createBottomTabNavigator ==> 自定義的底部Tab
NavigationActions 和 StackActions 可以獲取navigation的方法名
二、this.props.navigation使用的方法和屬性
詳細請看:
react-navigation 3.x版本的push、navigate、goback、pop、dispatch等常用方法
1. 應用中的每個頁面組件都會自動提供 this.props.navigation
this.props.navigation可以獲取的一些方法:
navigate
- 轉到另一個頁面, 計算出需要執行的操作 (常用)goBack
- 關閉活動屏幕並在堆棧中向後移動 (常用)addListener
- 訂閱導航生命周期的更新isFocused
- 函數返回true
如果屏幕焦點和false
否則。state
- 當前狀態/路由 (常用)setParams
- 對路由的參數進行更改 (常用)getParam
- 獲取具有回退的特定參數 (常用)dispatch
dangerouslyGetParent
- 返回父級 navigator 的函數
註意: this.props.navigation並不是在所有頁面(組件)中都可以使用,而是必須在StackNavigator、DrawerNavigator中聲明的screen組件,才可以使用this.props.navigation
也就是說,screen組件會自動獲得這個props
this.props.navigation
上還有一些方法取決於當前 navigator 的附加函數(StackNavigator 和 DrawerNavigator)
2. 如果是StackNavigator,除了以上方法,this.props.navigation還提供如下的一些方法:
push
- 推一個新的路由到堆棧 (常用)pop
- 返回堆棧中的上一個頁面 (常用)popToTop
- 跳轉到堆棧中最頂層的頁面 (常用)replace
- 用新路由替換當前路由- reset- 操作會擦除整個導航狀態,並將其替換為多個操作的結果。 (常用)
dismiss
- 關閉當前堆棧
3. 如果是DrawerNavigator,除了以上方法,this.props.navigation還提供如下的一些方法:
openDrawer
- 打開closeDrawer
- 關閉toggleDrawer
- 切換,如果是打開則關閉,反之亦然
由於筆者沒有使用過DrawerNavigator,在此就不做說明;
以上內容均摘自react-navigation的官網,但是官網有點繁瑣,寫此以自用,有讀者也是我的幸運。
三、react-navigation的特殊方法
===============================================================
==> 清空堆棧,跳轉指定頁面
import {NavigationActions, StackActions} from ‘react-navigation‘ const resetAction = StackAction.reset({ index: 0, actions: [NAvigationActions.navigate({ routeName: ‘HomeScreen‘})], }); //使用 this.props.navigation.dispatch(resetaction)
說明: 上面的方法是使用dispatch重寫了reset方法,
也可以直接使用reset方法:this.props.navigation.reset()
import { NavigationActions } from ‘react-navigation‘;
navigation.reset([NavigationActions.navigate({ routeName: ‘HomeScreen‘ })], 0)
========================================================================
//在不在StackNavigation的堆棧中的頁面,如何使用navigation
1.在主Navigator的組件中添加ref,並導出
//StackNavigator來自createStackNavigator方法 const MainNavigator = createAppContainer(StackNavigator); import {setTopLevelNavigator} from ‘xxx.js‘ export default calss Navigator extends Component{ render() { return( <MainNavigator ref={navigatorRef => {setTopLevelNavigator(navigatorRef )}} //setTopLevelNavigator來自需要使用的頁面 /> ) } }
說明: 將MainNavigator 通過ref 傳遞給 其他頁面傳過來的 setTopLevelNavigator
2.在需要使用的頁面,接收這個ref引用,如xxx.js
let _navigator; export function setTopLevelNavigator(navigatorRef ) { _navigator = navigatorRef } // 定義navigate 方法 function navigate(routeName, params) { _navigator && __navigator .dispatch( NavigationActions.navigate({ type: NavigationActions.NAVIGATE, routeName, params }) ) } // 定義dispatch方法 function dispatch(params) { _navigator && __navigator .dispatch( params ) } //使用,直接使用上面的方法即可 dispatch(resetAction) //resetAction同上 navigate("Home", {title: ‘profile‘})
說明: 通過setTopLevelNavigator去主導航頁面接收navigation相關的方法
========================================================================
==》阻止多次點擊重復跳轉同一頁面
const navigateOnce = (getStateForAction) => (action, lastState) => { const {type, routeName, params} = action; return ( lastState && (type === StackActions.PUSH) && //此處原先使用NavigationActions.NAVIGATE routeName === lastState.routes[lastState.routes.length - 1].routeName && JSON.stringify(params) === JSON.stringify(lastState.routes[lastState.routes.length - 1].params) ) ? null : getStateForAction(action, lastState) } //使用,MainNavigator是主導航頁面通過createAppContainer方法的返回值 MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)
說明: MainNavigator經過 getStateForAction 檢查校驗,阻止多次點擊跳轉相同頁面的情況發生
註意: 當你使用createSwitchNavigator時,就在路由數組外在套上一層switch數組,所以 lastState.routes[lastState.routes.length - 1] 可能取不到想要的值,因為還有一層數組
react-navigation的多次點擊重復跳轉同一頁面、不在堆棧路由頁面使用navigation方法的解決思路