如何使用 Typescript 构建 React Native 导航以进行属性传递
Posted
技术标签:
【中文标题】如何使用 Typescript 构建 React Native 导航以进行属性传递【英文标题】:How to structure React Native navigation for property passing with Typescript 【发布时间】:2021-05-22 11:57:51 【问题描述】:我有一个简单的 React Native 应用程序,我正在使用 Typescript 组合在一起,我正在尝试了解如何使导航正常工作。
我是一个内容部分以及选择一个在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-specific documentation 谈论通过导航属性,但没有解释这与 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>
);
;
NavigationTypes.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>
)
;
InstructionView.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
?
【问题讨论】:
【参考方案1】:这不起作用,因为
navigation
来自???某处???
navigation
对象来自组件的props
。当你的组件通过 Stack.Screen
加载时,react-navigation 会使用 props route
和 navigation
调用组件。
在打字稿方面,您需要声明 NavigationItems
组件 必须 使用此 navigation
属性调用。你如何做到这一点就是你在文档中看到的解释。
您声明一个 RootStackParamList
类型,将您的屏幕名称映射到所需的道具。
type RootStackParamList =
['Choose a topic']: undefined; // no required props
Instructions: IFileLink; // requires an IFileLink as props
;
您在创建Stack
实例时将此类型用作泛型。
const Stack = createStackNavigator<RootStackParamList>();
当您为NavigationItems
组件声明navigation
属性的类型时,您再次将此类型用作泛型。现在你的组件知道它会有一个prop navigate
,所以你可以调用this.props.navigate
。它还知道有关您可以导航到的位置的非常详细的信息。屏幕名称必须是'Choose a topic'
或'Instructions'
,否则会出现错误。它还知道所有屏幕的独特道具要求,因此如果您尝试导航到 Instructions
而不传递 IFileLink
作为第二个参数,则会出现错误。
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 />
Typescript Playground Link
【讨论】:
以上是关于如何使用 Typescript 构建 React Native 导航以进行属性传递的主要内容,如果未能解决你的问题,请参考以下文章
使用 create-react-app 和 Typescript 时如何在构建时加载 .md 文件?
如何将 CSS 模块与 Typescript、React 和 Webpack 一起使用?
typescript+reactjs+requirejs:如何将 react-dom 导入 typescript