我正在关注React-Navigation教程,并被卡在标题为Header interaction with its screen component的部分。教程中的The code在小吃提供的模拟器中运行良好,但我发现在本地运行时遇到以下错误:
Warning: Failed prop type: The prop 'onPress' is marked as required in 'Button', but its value is 'undefined'.
通过更改navigationOptions中的onPress事件分配,我设法使用expo-cli在我的本地机器上运行代码,如下所示(my snack here):
<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 />;
}
}
我的猜测是,这不是一个致命的错误,只是一个警告。
无论如何都会发生这种情况。 React Navigation文档状态:
React Navigation不保证您的屏幕组件将在标题之前安装。因为increaseCount参数是在componentDidMount中设置的,所以我们可能没有在navigationOptions中使用它。这通常不会成为问题,因为如果回调为null,onPress for Button和Touchable组件将不会执行任何操作。如果您在此处拥有自己的自定义组件,则应确保其按下处理程序道具的行为与null一致。
因此,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}
/>
),
};
};
在我看来,你的代码是正确的,而文档中的代码只是忽略了这个问题。
尝试使用navigation.getavram()而不是navigation.navigate()