代码之家  ›  专栏  ›  技术社区  ›  cseelus

如何将“从外部”链接到导航器(例如从全局页脚)

  •  4
  • cseelus  · 技术社区  · 7 年前

    具有 React Navigation 从外部

    <Provider store={store}>
      <View>
         <AppNavigator />
         <MyFooter /> // Link from here to a path/screen inside AppNavigator
      </View>
    </Provider>
    
    2 回复  |  直到 7 年前
        1
  •  9
  •   mradziwon    7 年前

    我想 refs 可能在这里工作。如果您想从同一级别使用Navigator,您可以使用react 参考文献 props MyFooter . 看看 example

    const AppNavigator = StackNavigator(SomeAppRouteConfigs);
    
    class App extends React.Component {
      someFunction = () => {
        // call navigate for AppNavigator here:
        this.navigator && this.navigator.dispatch({ type: 'Navigate', routeName, params });
      }
      render() {
        return (
          <View>
            <AppNavigator ref={nav => { this.navigator = nav; }} />
            <MyFooter someFunction={this.someFunction} />
          </View>
        );
      }
    }
    
        2
  •  3
  •   Charanjit Singh    5 年前

    转到此链接: https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

    反应导航版本:5。x

    有时,您需要从无法访问的位置触发导航操作 navigation 道具,例如Redux中间件。对于这种情况,您可以从导航容器中调度导航操作。

    支撑,参见 useNavigation .

    您可以通过 ref 并将其传递给 RootNavigation

    // App.js
    
    import { NavigationContainer } from '@react-navigation/native';
    import { navigationRef } from './RootNavigation';
    
    export default function App() {
      return (
        <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
      );
    }
    

    在下一步中,我们定义 ,这是一个简单的模块,具有调度用户定义的导航操作的功能。

    // RootNavigation.js
    
    import * as React from 'react';
    
    export const navigationRef = React.createRef();
    
    export function navigate(name, params) {
      navigationRef.current?.navigate(name, params);
    }
    
    // add other navigation functions that you need and export them
    

    然后,在任何javascript模块中,只需导入 并调用从中导出的函数。您可以在React组件之外使用这种方法,事实上,在React组件内部使用时,它同样有效。

    // any js module
    import * as RootNavigation from './path/to/RootNavigation.js';
    
    // ...
    
    RootNavigation.navigate('ChatScreen', { userName: 'Lucy' });
    

    navigate ,您可以添加其他导航操作:

    import { StackActions } from '@react-navigation/native';
    
    export function push(...args) {
      navigationRef.current?.dispatch(StackActions.push(...args));
    }
    

    请注意,需要呈现堆栈导航器来处理此操作。您可能需要检查 docs for nesting 了解更多详细信息。

    编写测试时,您可以模拟导航函数,并断言是否使用正确的参数调用了正确的函数。

    处理初始化

    当使用这种模式时,你需要记住几件事来避免应用程序崩溃。

    • 导航器需要渲染才能处理动作

    如果您尝试在不呈现导航器的情况下导航,或者在导航器安装完成之前导航,如果不进行处理,它将抛出并崩溃您的应用程序。因此,你需要添加一个额外的检查来决定在你的应用程序安装之前该做什么。

    例如,考虑以下场景,应用程序中的某个地方有一个屏幕,该屏幕在上调度redux操作 useEffect / componentDidMount 使用效果 / 总是被称为 儿童的 使用效果 .

    为了避免这种情况,你可以设置一个ref来告诉你你的应用已经完成安装,并在执行任何导航之前检查该ref。为此,我们可以使用 使用效果

    // App.js
    
    import { NavigationContainer } from '@react-navigation/native';
    import { navigationRef, isMountedRef } from './RootNavigation';
    
    export default function App() {
      React.useEffect(() => {
        isMountedRef.current = true;
    
        return () => (isMountedRef.current = false);
      }, []);
    
      return (
        <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
      );
    }
    

    也从我们的 根导航

    // RootNavigation.js
    
    import * as React from 'react';
    
    export const isMountedRef = React.createRef();
    
    export const navigationRef = React.createRef();
    
    export function navigate(name, params) {
      if (isMountedRef.current && navigationRef.current) {
        // Perform navigation if the app has mounted
        navigationRef.current.navigate(name, params);
      } else {
        // You can decide what to do if the app hasn't mounted
        // You can ignore this, or add these actions to a queue you can call later
      }
    }