React-Navigation - взаимодействие заголовка с компонентом экрана, тип пропущенного пропа - PullRequest
0 голосов
/ 19 февраля 2019

Я следую учебному пособию React-Navigation и застрял в разделе, озаглавленном Взаимодействие заголовка с компонентом экрана . Код в учебнике отлично работает в эмуляторе, предоставленном на закуску, но я обнаружил, что при локальном запуске я обнаружил следующую ошибку:

Warning: Failed prop type: The prop 'onPress' is marked as required in 'Button', but its value is 'undefined'.

Мне удалосьчтобы заставить код работать на моем локальном компьютере с помощью expo-cli, изменив назначение события onPress в navigationOptions следующим образом ( моя закуска здесь ):

<Button
     onPress={()=>{navigation.getParam('increaseCount')()}}
   //onPress={navigation.getParam('increaseCount')} - as in tutorial
     title="+1"
     color={Platform.OS === 'ios' ? '#fff' : null}
/>

Я надеюсь, что кто-то может иметьнекоторое понимание того, почему это так.Я проверил, и я использую ту же версию Expo (v.32.0) локально.

Листинг App.js:

import React from 'react';
import { Button, Image, Platform, View, Text } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';

class LogoTitle extends React.Component {
  render() {
    return (
      <Image
        source={require('./spiro.png')}
        style={{ width: 30, height: 30 }}
      />
    );
  }
}

class HomeScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    return {
      headerTitle: <LogoTitle />,
      headerRight: (
        <Button
          onPress={()=>{navigation.getParam('increaseCount')()}}
          //onPress={navigation.getParam('increaseCount')}
          title="+1"
          color={Platform.OS === 'ios' ? '#fff' : null}
        />
      ),
    };
  };

  componentWillMount() {
    this.props.navigation.setParams({ increaseCount: this._increaseCount });
  }

  state = {
    count: 0,
  };

  _increaseCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
        <Text>Count: {this.state.count}</Text>
        <Button
          title="Go to Details"
          onPress={() => {
            /* 1. Navigate to the Details route with params */
            this.props.navigation.navigate('Details', {
              itemId: 86,
              otherParam: 'First Details',
            });
          }}
        />
      </View>
    );
  }
}

class DetailsScreen extends React.Component {
  static navigationOptions = ({ navigation, navigationOptions }) => {
    const { params } = navigation.state;

    return {
      title: params ? params.otherParam : 'A Nested Details Screen',
      /* These values are used instead of the shared configuration! */
      headerStyle: {
        backgroundColor: navigationOptions.headerTintColor,
      },
      headerTintColor: navigationOptions.headerStyle.backgroundColor,
    };
  };

  render() {
    /* 2. Read the params from the navigation state */
    const { params } = this.props.navigation.state;
    const itemId = params ? params.itemId : null;
    const otherParam = params ? params.otherParam : null;

    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
        <Text>itemId: {JSON.stringify(itemId)}</Text>
        <Text>otherParam: {JSON.stringify(otherParam)}</Text>
        <Button
          title="Update the title"
          onPress={() =>
            this.props.navigation.setParams({ otherParam: 'Updated!' })
          }
        />
        <Button
          title="Go to Details... again"
          onPress={() => this.props.navigation.navigate('Details')}
        />
        <Button
          title="Go back"
          onPress={() => this.props.navigation.goBack()}
        />
      </View>
    );
  }
}

const RootStack = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    Details: {
      screen: DetailsScreen,
    },
  },
  {
    initialRouteName: 'Home',
    defaultNavigationOptions: {
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    },
  }
);

const AppContainer = createAppContainer(RootStack);

export default class App extends React.Component {
  render() {
    return <AppContainer />;
  }
}

Ответы [ 2 ]

0 голосов
/ 07 мая 2019

Я предполагаю, что это не фатальная ошибка, а просто предупреждение.

Это произойдет в любом случае. Состояние React Navigation docs:

React Navigation не гарантирует, что ваш компонент экрана будет смонтирован перед заголовком.Поскольку параметр extensionCount задается в componentDidMount, он может быть недоступен для нас в navigationOptions.Обычно это не будет проблемой, потому что компоненты onPress for Button и Touchable ничего не сделают, если обратный вызов равен нулю.Если у вас есть свой собственный компонент, вы должны убедиться, что он работает так, как ожидалось, с нулем для его свойства обработчика прессы.

Итак, функция navigationOptions будет вызвана дважды:

  • Первый раз перед componentDidMount.Здесь getParam вернет undefined.
  • Второй раз после componentDidMount.

На что Button жалуется, это первый раз.Он не любит onPress, установленный на undefined.

Вы можете проверить это с помощью console.log из navigationOptions:

class HomeScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    console.log(navigation.getParam('increaseCount'))
    return {
      headerTitle: <LogoTitle />,
      headerRight: (
        <Button
          onPress={()=>{navigation.getParam('increaseCount')()}}
          //onPress={navigation.getParam('increaseCount')}
          title="+1"
          color={Platform.OS === 'ios' ? '#fff' : null}
        />
      ),
    };
  };

На мой взгляд, ваш код правильный,в то время как код из документов просто игнорирует эту проблему.

0 голосов
/ 05 апреля 2019

Попробуйте вместо navigation.getParam () использовать navigation.navigate ()

...