首页 > 解决方案 > 如何使用 Typescript 构建 React Native 导航以进行属性传递

问题描述

我有一个简单的 React Native 应用程序,我正在使用 Typescript 组合在一起,我正在尝试了解如何使导航正常工作。

I a list of content sections and when one is selected to open the chosen article in a webview. 我无法理解的是我应该如何将 webview 的 URL 传递到包含它的视图中。导航列表和 Web 视图在被选中时都应该填满屏幕。

就目前情况而言,我的基本组件GuidanceNavigation包含一个Stack.Navigator用于Stack.Screen列出NavigationItems所有主题的视图和一个Stack.Screen用于InstructionView包含 web 视图以显示说明的视图。

就目前情况而言,这些都是React.Component类型,我不清楚的部分是,当我在NavigationItems视图中时,我选择了一个选项,并且我需要父视图将视图替换为NavigationItems,并InstructionView提供InstructionView所选的标题和文件位置文章。据我所知,React Navigation 做了一些涉及传递一些导航属性的魔法,但我无法弄清楚这应该如何在 Typescript 上下文中工作,或者我如何通过 Stack Navigator 传递我的类型化对象,甚至是否Stack Navigator 是在这种情况下使用的正确组件。特定于Typescript 的文档讨论了通过导航属性,但没有解释这与navigator似乎在 JavaScript 中可用于实际执行导航的对象。

我的代码看起来像这样,自从我使用 React 和我第一次使用 react-native 以来已经有一段时间了,所以它可能既不优秀也不惯用:

GuidanceNavigation.tsx:

const Stack = createStackNavigator();

export class GuidanceNavigation extends React.Component<{}, {}>  {

  render(): JSX.Element {
    return (
      <SafeAreaView style={styles.container} >
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen name="Choose a topic" component="NavigationItems" />
            <Stack.Screen name="Instructions" component="InstructionView" />
      </Stack.Navigator>
      </NavigationContainer>
      </SafeAreaView>
    );
  };

}

导航类型.ts:

export interface IFileLink {
    title: string,
    file: string
}

NavigationItems.tsx:

import { IFileLink } from './NavigationTypes';

export class NavigationItems extends React.Component<{}, {}>  {

  itemId: number = 0;
  
  readonly items = [
    {
      section: R.strings.menu_steps,
      values: [
    { title: R.strings.menu_getting_started, file: "./assets/html/getting-started.html" },
     // and so on

      ]
    },
    {
      section: R.strings.menu_guidance,
      values: [
    { title: R.strings.menu_glossary, file: "./assets/html/glossary.html" },
        // etc
      ]
    }
  ];

  itemList(itemList: Array<IFileLink>): JSX.Element[] {
    return itemList.map((it) => this.item(it));
  };

  navigateToFile(link:IFileLink) {
    console.log("Navigation to "+link.title);
    // This does not work because navigation comes from ??? somewhere???
    navigation.navigate('Instructions', link);
  };

  item(fileLink:IFileLink): JSX.Element {
    return(
      <Button
    key= { this.itemId++ }
    title= { fileLink.title }
    onPress= {() =>
      this.navigateToFile(fileLink)
    }
      />
    );
  };

  render(): JSX.Element {
    return (
      <ScrollView>
          <Text style={styles.sectionTitle}>{this.items[0].section}</Text>
          {this.itemList(this.items[0].values)}
          <Text style={styles.sectionTitle}>{this.items[1].section}</Text>
          {this.itemList(this.items[1].values)}
      </ScrollView>
    )
  };

}

指令视图.tsx:

import { IFileLink } from './NavigationTypes';

export class InstructionView extends React.Component<IFileLink> {

  private fileLink: IFileLink;

  constructor(fl: IFileLink) {
    super(fl);
    this.fileLink = fl;
  }

  render(): JSX.Element {
    return (
        <WebView
          source={{ uri: this.fileLink.file }}
          />
    );
  }
}

当在该列表中选择项目时,如何确保使用所需的属性从NavigationItems到 导航?InstructionView

标签: typescriptreact-nativereact-navigation

解决方案


这不起作用,因为navigation来自 ??? 某处???

navigation对象来自props组件的。当您的组件通过 加载时Stack.Screen,react-navigation 会使用 propsroutenavigation.

在打字稿方面,您需要声明必须使用此道具调用NavigationItems组件。你如何做到这一点就是你在文档中看到的解释。navigation

您声明一个RootStackParamList类型,将您的屏幕名称映射到所需的道具。

type RootStackParamList = {
    ['Choose a topic']: undefined; // no required props
    Instructions: IFileLink; // requires an IFileLink as props
};

您在创建Stack实例时将此类型用作泛型。

const Stack = createStackNavigator<RootStackParamList>();

navigation当您声明组件的prop类型时,您再次将此类型用作泛型NavigationItems。现在你的组件知道它会有一个 prop navigate,所以你可以调用this.props.navigate. 它还知道有关您可以导航到的位置的非常详细的信息。屏幕名称必须是,'Choose a topic'否则'Instructions'您将收到错误消息。它还知道所有屏幕的独特道具要求,因此如果您尝试导航到Instructions而不传递 anIFileLink作为第二个参数,则会出现错误。

import { StackNavigationProp, createStackNavigator } from '@react-navigation/stack';

type ItemsProps = {
    navigation: StackNavigationProp<RootStackParamList, 'Choose a topic'>;
};

export class NavigationItems extends React.Component<ItemsProps, {}>  {

    navigateToFile(link: IFileLink) {
        console.log("Navigation to " + link.title);
        // can now navigate via props
        this.props.navigation.navigate('Instructions', link);
    };

    /*...*/
}

您的Navigator. 您需要传递组件本身,而不是它们的string名称。

<Stack.Screen name="Choose a topic" component={NavigationItems} />
<Stack.Screen name="Instructions" component={InstructionView} />

打字稿游乐场链接


推荐阅读