发布于 2026-01-06 1 阅读
0

React Navigation with Typescript

React Navigation with Typescript

所以……你想用 Typescript 构建一个 React Native 应用,并且决定使用 React Navigation 作为导航库。

你已经完成了所有 TypeScript 的配置,并且你的应用程序可以运行了!

添加 React Navigation 后一切就都好了!

但是……你添加了一些需要参数的屏幕,还有一些屏幕需要编辑标题等等。这方面的信息并不多……

以下是我如何使用 React Navigation 和 TypeScript 的一些代码片段。

免责声明

实现类型化 React 导航的方法有很多种。这里仅列举一些示例,具体命名应根据你的应用程序进行调整。

欢迎提出其他解决方法!

首先,类和函数的区别……

我非常喜欢使用带有 Hooks 的函数组件。
但目前使用函数组件时存在热重载问题。
参见:https://github.com/facebook/react-native/issues/10991

它就是行不通。或许可以用类来封装函数式组件,但希望这个问题能尽快得到解决!
https://mobile.twitter.com/dan_abramov/status/1125846420949434368

我将使用基于https://github.com/react-navigation/hooks的 useNavigation hook 。
但由于该仓库不太活跃,我只是“借用”了这个函数并稍作修改:

import { useContext } from 'react';
import {
  NavigationScreenProp,
  NavigationRoute,
  NavigationContext,
} from 'react-navigation';

export function useNavigation<Params>() {
  return useContext(NavigationContext) as NavigationScreenProp<
    NavigationRoute,
    Params
  >;
}
Enter fullscreen mode Exit fullscreen mode

因此,我的示例将同时包含类组件和函数式组件。

更新标题和导航

类组件

import React, { Component } from 'react';
import { Button, Text, View } from 'react-native';
import {
  NavigationParams,
  NavigationScreenProp,
  NavigationState,
} from 'react-navigation';

interface Props {
  navigation: NavigationScreenProp<NavigationState, NavigationParams>;
}

class TestScreen extends Component<Props> {
  public static navigationOptions = {
    title: 'Test Screen',
  };

  render() {
    const { navigation } = this.props;
    return (
      <View>
        <Text>Test Screen</Text>
        <Button
          title="Button"
          onPress={() => {
            navigation.navigate('anotherTestScreen');
          }}
        />
      </View>
    );
  }
}

export default TestScreen;
Enter fullscreen mode Exit fullscreen mode

请注意,只有直接设置在导航栏上的屏幕才具有 navigation 属性。如果您希望子组件能够访问 navigation,可以这样做:

import React, { Component } from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationInjectedProps, withNavigation } from 'react-navigation';

class TestComponent extends Component<NavigationInjectedProps> {
  render() {
    const { navigation } = this.props;
    return (
      <Button
        title="Button"
        onPress={() => {
          navigation.navigate('anotherTestScreen');
        }}
      />
    );
  }
}

export default withNavigation(TestComponent);
Enter fullscreen mode Exit fullscreen mode

功能组件

import React from 'react';
import { Button, Text, View } from 'react-native';
import { useNavigation } from '../hooks/useNavigation';

const AnotherTestScreen = () => {
  const navigation = useNavigation();
  return (
    <View>
      <Text>Test Screen</Text>
      <Button
        title="Button"
        onPress={() => {
          navigation.navigate('paramScreen', { text: 'Hi!' });
        }}
      />
    </View>
  );
};

AnotherTestScreen.navigationOptions = {
  title: 'Another Test Screen',
};

export default AnotherTestScreen;
Enter fullscreen mode Exit fullscreen mode

屏幕的输入参数

类组件

import React, { Component } from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationScreenProp, NavigationState } from 'react-navigation';

interface NavigationParams {
  text: string;
}

type Navigation = NavigationScreenProp<NavigationState, NavigationParams>;

interface Props {
  navigation: Navigation;
}

class ParamScreen extends Component<Props> {
  public static navigationOptions = ({
    navigation,
  }: {
    navigation: Navigation;
  }) => ({
    title: navigation.state.params ? navigation.state.params.text : '',
  });

  render() {
    const { navigation } = this.props;
    const {
      state: { params },
    } = navigation;
    return (
      <View>
        <Text>Param: {params ? params.text : ''}</Text>
        <Button
          title="Button"
          onPress={() => {
            navigation.navigate('anotherParamScreen', { text: 'Hello!' });
          }}
        />
      </View>
    );
  }
}

export default ParamScreen;
Enter fullscreen mode Exit fullscreen mode

你可能会问,为什么要费劲写这么多额外的类型定义代码呢?为什么不直接用 ` ?` 呢any
好吧,这个例子可能不是最好的,但现在参数都已类型化,你可以在编辑器中获得智能提示:

功能组件

import React from 'react';
import { Button, Text, View } from 'react-native';
import {
  NavigationScreenProp,
  NavigationState,
  StackActions,
  NavigationActions,
} from 'react-navigation';
import { useNavigation } from '../hooks/useNavigation';

interface NavigationParams {
  text: string;
}

type Navigation = NavigationScreenProp<NavigationState, NavigationParams>;

const AnotherParamScreen = () => {
  const navigation = useNavigation<NavigationParams>();
  const {
    state: { params },
  } = navigation;
  return (
    <View>
      <Text>Param: {params ? params.text : ''}</Text>
      <Button
        title="Button"
        onPress={() => {
          const resetAction = StackActions.reset({
            index: 0,
            actions: [NavigationActions.navigate({ routeName: 'testScreen' })],
          });
          navigation.dispatch(resetAction);
        }}
      />
    </View>
  );
};

AnotherParamScreen.navigationOptions = ({
  navigation,
}: {
  navigation: Navigation;
}) => ({
  title: navigation.state.params ? navigation.state.params.text : '',
});

export default AnotherParamScreen;

Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/andreasbergqvist/react-navigation-with-typescript-29ka