Добавить сильную типизацию для реагирования на навигационные опоры

Я использую typescript в своем проекте, посвященном реакции (expo).

В проекте используется интерактивная навигация, поэтому на моих экранах я могу установить navigationOptions, и у меня есть доступ к prop 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
    })
}

Каким будет лучший способ обработки реакции-навигации в качестве реквизита для компонентов.

Ответ 1

Просто добавьте 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>
        );
      }
    }

Ответ 2

Это работает:

static navigationOptions = ({ navigation }: NavigationScreenProps) => ({
  ...
})

Ответ 3

У меня такая же проблема, и вот мое решение:

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
  })
}

Вы можете захотеть объявить тип NavigationOptionsFn<TParams> в некоторый файл d.ts, чтобы он работал глобально.

Ответ 4

 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 { .... }

Ответ 5

public static navigationOptions: NavigationScreenConfig<NavigationStackScreenOptions> = 
    ({navigation}) => ({/* Your options... */})

Ответ 6

Вместо того, чтобы описывать вручную все ваши функции навигации (например: навигация), в интерфейсе вашего Props вы можете напрямую расширять NavigationScreenProp.

В моем случае это было обязательным, чтобы остановить eslint от выдачи ошибки.

import { StackNavigator, NavigationScreenProp } from 'react-navigation';

export interface HomeScreenProps extends NavigationScreenProp {
/* 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>
    );
  }
}

Ответ 7

Это похоже на работу:

public static navigationOptions: NavigationScreenOptionsGetter<
  NavigationScreenOptions
> = (navigation, stateProps) => ({
  title: navigation.state.params.someValue,
});

Ответ 8

Раздел does not work содержит ошибку, если ваш tsconfig.json имеет "strictNullChecks": true. В этом случае у вас действительно есть ошибка, потому что в строке

navigation.state.params.someValue

params является обязательным. Что вы можете сделать, это проверить, передано ли значение внутрь, и указать значение по умолчанию, например:

title: navigation.state.params && navigation.state.params.someValue || 'Default title'

Ответ 9

Если кто-то все еще испытывает эту проблему при расширении 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>;
  };

from react-navigation.d.ts