最近需求维护老的 RN 项目,需求晋级到最新的版本。晋级下来,首要涉及第三方库适配 androidx 及 react-navigaiton6 的晋级。androidx 的晋级首要是一些库的晋级,包含不维护的库 fork 或许建议 pr,相对比较惯例。首要的工作量在 react-navigation 这一次层。(参照 5.x 的晋级文档)

一般改动点

navigation 4.x 之前经过 route configuration 装备,5.x 以上经过组件的嵌套,和 react-router 比较类似。可参照文档,修正tab,nav嵌套关系

// 4.x
const RootStack = createStackNavigator({
    Home: { screen: HScreen, navigationOptions: { title: 'My app' },
})
// 5.x
const RootStack = () => {
    return (
        <Stack.Navigator>
            <Stack.Screen name='Home' component={HScreen} options={{ title: 'My app' }} />
        </Stack.Navigator>
    );
}

首要改动点

  • 传值(params)

    5.x 获取params,之前经过navigation拿到state,现在需求从route取,this.props.route 或许经过 useRoute 拿到route目标。

  • 事情订阅(events)

    订阅的事情只要(focus,blur),之前的willxx,didxx需求修正,remove的办法为了兼容hooks,改成函数回来的办法,既this.unsubsubscribe()

  • 跳转(dispatch action)

    action 改动比较大,之前的NavigationActions被移除,改成了CommonAction,之前比较臃肿的写法也变得简洁了些。

    // 4.x
    const navigateAction = NavigationActions.navigate({
    	routeName: 'Profile',
    	params: {},
    	action: NavigationActions.navigate({ routeName: 'SubProfileRoute' }),
    });
    // 5.x reset
    const navigateAction = actionToCustom(1, [{ name: 'Profile' }, { name: 'SubProfileRoute' }]);
    // 多级跳转使用 state 装备
    const navigateAction = CommonActions.reset({
    	index: 0,
    	params: { version: '6.x' },
    	routes: [{ name: 'Profile', state: { routes: [{ name: 'SubProfileRoute' }], index: 0 } }],
    });
    // 5.x goback
    const backAction = {
    	...CommonActions.goBack(),
    	// key从route中获取
    	source: key,
    };
    // dispatch
    navigation.dispatch(action);
    
  • withNavigation(子组件传递navigation)

    4.x版簿本组件能够使用withNavigation包装,使用onRef获取组件目标引用。新版本移除withNavigation,需求手动处理onRef,可改成ref或许在子组件中处理下onRef

    // 经过 function component 包装传入 navigaiton,route
    const UserBannerWrap = (props)=>{
     const navigation = useNavigation();
     const route = useRoute();
     const bannerRef = useRef();
     useEffect(()=>{
         props.onRef && props.onRef(bannerRef.current)
     })
     return (
         // 可兼容 class component
         <View {...props} navigation={navigation} route={route} ref={bannerRef} />
     );
    }
    // withNavigation 可从 @react-navigation/compat 包中获取,兼容老的Api,但是获取route中的params,还需求手动处理,感觉没有太必要
    const UserBannerWrap = withNavigation(ClassView)
    
  • 自定义路由(阻拦action)

    5.x版本无法经过顶层的navigator component获取getStateForAction及action changge的办法。如需求阻拦action type,比方BACK,RESET等,需求修正createStackNavigator,createBottomTabNavigator的完成办法。

    比方要阻拦navStack,可检查createStackNavigator的完成代码,一般在同名的xx.d.ts的根目录的src下,也可直接检查package.json的types机source的路径。然后复制下,可参照文档。

    一般只需求从实例化Router(可为StackRouter,tabRouter只是类型不同), 然后即可阻拦getStateForAction,getStateForRouteNamesChange等办法,结合业务处理跳转。在经过useNavigationBuilder办法中传入自定义的Router,导出即可。