为反应导航道具添加强类型
Add strong typing for react navigation props
我在我的 react-native 项目 (expo) 中使用 typescript。
该项目使用反应导航,所以在我的屏幕上我可以设置 navigationOptions
并且我可以访问道具 navigation
.
现在我正在尝试对这些进行强类型化,以便获得有关可设置哪些属性的提示。
interface NavStateParams {
someValue: string
}
interface Props extends NavigationScreenProps<NavStateParams> {
color: string
}
class Screen extends React.Component<Props, any> {
// This works fine
static navigationOptions: NavigationStackScreenOptions = {
title: 'ScreenTitle'
}
// Does not work
static navigationOptions: NavigationStackScreenOptions = ({navigation, screenProps }) => ({
title: navigation.state.params.someValue
})
}
将反应导航作为组件的道具处理的最佳方式是什么。
我有同样的问题,这是我的解决方案:
import * as React from 'react'
import { NavigationScreenProps, NavigationStackScreenOptions } from 'react-navigation'
interface NavStateParams {
someValue: string
}
// tslint:disable-next-line:no-any
type NavigationOptionsFn<TParams=any> = (props: NavigationScreenProps<TParams>) => NavigationStackScreenOptions
class Screen extends React.Component {
// This should works fine
static navigationOptions: NavigationOptionsFn<NavStateParams> = ({ navigation, screenProps }) => ({
title: navigation.state.params.someValue
})
}
您可能希望在某些 d.ts
文件中声明 NavigationOptionsFn<TParams>
类型以使其在全球范围内工作。
只需将 NavigationType 添加到您的道具中,如下所示:
import { StackNavigator, NavigationScreenProp } from 'react-navigation';
export interface HomeScreenProps {
navigation: NavigationScreenProp<any,any>
};
export class HomeScreen extends React.Component<HomeScreenProps, object> {
render() {
return (
<View style={styles.container}>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
这似乎有效:
public static navigationOptions: NavigationScreenOptionsGetter<
NavigationScreenOptions
> = (navigation, stateProps) => ({
title: navigation.state.params.someValue,
});
public static navigationOptions: NavigationScreenConfig<NavigationStackScreenOptions> =
({navigation}) => ({/* Your options... */})
这个有效:
static navigationOptions = ({ navigation }: NavigationScreenProps) => ({
...
})
yarn add --dev @types/jest @types/react-navigation
import { NavigationScreenProps } from "react-navigation";
export interface ISignInProps extends NavigationScreenProps<{}> { userStore: IUserStore }
export class SignInScreen extends React.Component { .... }
无需手动描述所有 navigation functions(例如:导航),您可以在道具界面中直接扩展 NavigationScreenProps
.
在我的例子中,必须阻止 eslint 产生错误。
import { StackNavigator, NavigationScreenProps } from 'react-navigation';
export interface HomeScreenProps extends NavigationScreenProps {
/* your custom props here */
};
export class HomeScreen extends React.Component<HomeScreenProps, object> {
render() {
return (
<View style={styles.container}>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
如果您的 tsconfig.json
有 "strictNullChecks": true
,则 does not work
部分包含错误。在这种情况下,你确实有一个错误,因为在行
navigation.state.params.someValue
params
是可选的。您可以做的是检查该值是否在内部传递,否则提供默认值,例如:
title: navigation.state.params && navigation.state.params.someValue || 'Default title'
如果有人在扩展 NavigationScreenProps
时仍然遇到此问题,那么您可以正确输入 navigationOptions
等以及您自己的道具:
interface Props extends NavigationScreenProps {
someProp: string;
anotherProp: string;
}
export const SomeGreatScreen: NavigationScreenComponent<NavigationParams, {}, Props> = ({
someProp,
anotherProp,
}) => {
...
};
而 NavigationScreenComponent<Props>
导致解构属性的类型错误 { someProp, anotherProp }
,无法识别道具的扩展,NavigationScreenComponent<NavigationParams, {}, Props>
做到了。这似乎是由于需要将扩展道具类型作为第三个参数发送:
export type NavigationScreenComponent<
Params = NavigationParams,
Options = {},
Props = {}
> = React.ComponentType<NavigationScreenProps<Params, Options> & Props> & {
navigationOptions?: NavigationScreenConfig<Options>;
};
我认为 react-navigation
5.X 现在更简单了。以下是如何键入提示 navigation
道具传递给 screens/components:
export default class Header extends React.Component<{
navigation: StackNavigationHelpers;
}> {
...
}
Ps:使用这些版本进行测试
"@react-navigation/native": "^5.2.3",
"@react-navigation/stack": "^5.3.1",
如果您要传递由
定义的 navigation
道具
let navigation = useNavigation()
对于一个组件,最好的输入方式是:
import {NavigationProp, ParamListBase} from '@react-navigation/native';
navigation: NavigationProp<ParamListBase>
更新:
这是一种更好的强导航类型方法,使用最新的 @react-navigation
版本 (6.x
)
完整示例:
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
type RootStackParamList = {
Pdp: undefined; //current screen
PdpComments: {slug: string}; // a screen that we are
// navigating to, in the current screen,
// that we should pass a prop named `slug` to it
Sellers: {data: Array<string>};
Favorites: undefined; // a screen that we are navigating to
// in the current screen, that we don't pass any props to it
};
interface IPdpPageProps {
navigation: NativeStackNavigationProp<RootStackParamList, 'Pdp'>;
}
// Since our screen is in the stack, we don't need to
// use `useNavigation()` to provide the `navigation` to
// our component, we just need to read it as a prop
function Pdp({navigation}: IPdpPageProps) {
return ...
}
最小配置,版本为 6.x
import { NavigationProp } from "@react-navigation/native";
interface RouterProps {
navigation: NavigationProp<any, any>;
}
<TouchableOpacity onPress={() => navigation.navigate('Home')}>
<Text>Navigate to Home</Text>
</TouchableOpacity>
我在我的 react-native 项目 (expo) 中使用 typescript。
该项目使用反应导航,所以在我的屏幕上我可以设置 navigationOptions
并且我可以访问道具 navigation
.
现在我正在尝试对这些进行强类型化,以便获得有关可设置哪些属性的提示。
interface NavStateParams {
someValue: string
}
interface Props extends NavigationScreenProps<NavStateParams> {
color: string
}
class Screen extends React.Component<Props, any> {
// This works fine
static navigationOptions: NavigationStackScreenOptions = {
title: 'ScreenTitle'
}
// Does not work
static navigationOptions: NavigationStackScreenOptions = ({navigation, screenProps }) => ({
title: navigation.state.params.someValue
})
}
将反应导航作为组件的道具处理的最佳方式是什么。
我有同样的问题,这是我的解决方案:
import * as React from 'react'
import { NavigationScreenProps, NavigationStackScreenOptions } from 'react-navigation'
interface NavStateParams {
someValue: string
}
// tslint:disable-next-line:no-any
type NavigationOptionsFn<TParams=any> = (props: NavigationScreenProps<TParams>) => NavigationStackScreenOptions
class Screen extends React.Component {
// This should works fine
static navigationOptions: NavigationOptionsFn<NavStateParams> = ({ navigation, screenProps }) => ({
title: navigation.state.params.someValue
})
}
您可能希望在某些 d.ts
文件中声明 NavigationOptionsFn<TParams>
类型以使其在全球范围内工作。
只需将 NavigationType 添加到您的道具中,如下所示:
import { StackNavigator, NavigationScreenProp } from 'react-navigation';
export interface HomeScreenProps {
navigation: NavigationScreenProp<any,any>
};
export class HomeScreen extends React.Component<HomeScreenProps, object> {
render() {
return (
<View style={styles.container}>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
这似乎有效:
public static navigationOptions: NavigationScreenOptionsGetter<
NavigationScreenOptions
> = (navigation, stateProps) => ({
title: navigation.state.params.someValue,
});
public static navigationOptions: NavigationScreenConfig<NavigationStackScreenOptions> =
({navigation}) => ({/* Your options... */})
这个有效:
static navigationOptions = ({ navigation }: NavigationScreenProps) => ({
...
})
yarn add --dev @types/jest @types/react-navigation
import { NavigationScreenProps } from "react-navigation";
export interface ISignInProps extends NavigationScreenProps<{}> { userStore: IUserStore }
export class SignInScreen extends React.Component { .... }
无需手动描述所有 navigation functions(例如:导航),您可以在道具界面中直接扩展 NavigationScreenProps
.
在我的例子中,必须阻止 eslint 产生错误。
import { StackNavigator, NavigationScreenProps } from 'react-navigation';
export interface HomeScreenProps extends NavigationScreenProps {
/* your custom props here */
};
export class HomeScreen extends React.Component<HomeScreenProps, object> {
render() {
return (
<View style={styles.container}>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
如果您的 tsconfig.json
有 "strictNullChecks": true
,则 does not work
部分包含错误。在这种情况下,你确实有一个错误,因为在行
navigation.state.params.someValue
params
是可选的。您可以做的是检查该值是否在内部传递,否则提供默认值,例如:
title: navigation.state.params && navigation.state.params.someValue || 'Default title'
如果有人在扩展 NavigationScreenProps
时仍然遇到此问题,那么您可以正确输入 navigationOptions
等以及您自己的道具:
interface Props extends NavigationScreenProps {
someProp: string;
anotherProp: string;
}
export const SomeGreatScreen: NavigationScreenComponent<NavigationParams, {}, Props> = ({
someProp,
anotherProp,
}) => {
...
};
而 NavigationScreenComponent<Props>
导致解构属性的类型错误 { someProp, anotherProp }
,无法识别道具的扩展,NavigationScreenComponent<NavigationParams, {}, Props>
做到了。这似乎是由于需要将扩展道具类型作为第三个参数发送:
export type NavigationScreenComponent<
Params = NavigationParams,
Options = {},
Props = {}
> = React.ComponentType<NavigationScreenProps<Params, Options> & Props> & {
navigationOptions?: NavigationScreenConfig<Options>;
};
我认为 react-navigation
5.X 现在更简单了。以下是如何键入提示 navigation
道具传递给 screens/components:
export default class Header extends React.Component<{
navigation: StackNavigationHelpers;
}> {
...
}
Ps:使用这些版本进行测试
"@react-navigation/native": "^5.2.3",
"@react-navigation/stack": "^5.3.1",
如果您要传递由
定义的navigation
道具
let navigation = useNavigation()
对于一个组件,最好的输入方式是:
import {NavigationProp, ParamListBase} from '@react-navigation/native';
navigation: NavigationProp<ParamListBase>
更新:
这是一种更好的强导航类型方法,使用最新的 @react-navigation
版本 (6.x
)
完整示例:
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
type RootStackParamList = {
Pdp: undefined; //current screen
PdpComments: {slug: string}; // a screen that we are
// navigating to, in the current screen,
// that we should pass a prop named `slug` to it
Sellers: {data: Array<string>};
Favorites: undefined; // a screen that we are navigating to
// in the current screen, that we don't pass any props to it
};
interface IPdpPageProps {
navigation: NativeStackNavigationProp<RootStackParamList, 'Pdp'>;
}
// Since our screen is in the stack, we don't need to
// use `useNavigation()` to provide the `navigation` to
// our component, we just need to read it as a prop
function Pdp({navigation}: IPdpPageProps) {
return ...
}
最小配置,版本为 6.x
import { NavigationProp } from "@react-navigation/native";
interface RouterProps {
navigation: NavigationProp<any, any>;
}
<TouchableOpacity onPress={() => navigation.navigate('Home')}>
<Text>Navigate to Home</Text>
</TouchableOpacity>