我正在尝试在我的反应启动启动移动应用程序中通过GraphQl显示一些内容。我不知道如何将这些数据传递给我的渲染方法。这是源代码。我需要能够在渲染中显示单元对象的内容。当我尝试引用this.props.singletour时,React会引发错误。我不知道的另一件事是如何将导航在渲染中接收到的参数传递到GetTournament GraphQl查询。理想情况下,我希望ID:Inside getTournament包含Navigation.getParam('itemID','no-id'),而不是硬编码ID。同样,当我在异步方法调用中访问此参数时,React会引发错误...任何帮助将不胜感激!
class DetailsScreen extends React.Component {
async componentDidMount() {
try {
const graphqldata = await API.graphql(graphqlOperation(GetTournament, { id: "4e00bfe4-6348-47e7-9231-a8b2e722c990" }))
console.log('graphqldata:', graphqldata)
this.setState({ singletour: graphqldata.data.getTournament })
console.log('singletour:', this.state.singletour)
} catch (err) {
console.log('error: ', err)
}
}
render() {
/* 2. Get the param, provide a fallback value if not available */
const { navigation } = this.props;
const itemId = navigation.getParam('itemId', 'NO-ID');
const otherParam = navigation.getParam('otherParam', 'some default value');
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="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
我想我知道您要做什么,并且可以通过重构代码来实现。
这就是我要做的:
- 在组件的
constructor
中捕获导航参数,并将其保存到state
。 - 在状态下为单元图设置初始值。在状态下设置
loaded
的值。loaded
值将使我们能够确定数据是否成功返回。 - 重构您的
componentDidMount
,以便使用现在存储在状态的itemId
。 - 重构您的
console.log
检查您是否设置了状态,因为这尚未正确执行。 - 在
render
中,从state
中汲取值,并且数据是否为loaded
。您可能希望显示一些加载屏幕或根本不想处理它。
这是重构:
class DetailsScreen extends React.Component {
constructor (props) {
super(props);
// capture the values that you have passed via your navigation in the constructor
const { navigation } = props;
const itemId = navigation.getParam('itemId', 'NO-ID');
const otherParam = navigation.getParam('otherParam', 'some default value');
this.state = {
itemId: itemId,
otherParam: otherParam,
loaded: false,
singletour: [] // you don't state what singletour is but you should set a default value here
};
}
async componentDidMount () {
try {
// we can now use the state value for itemId as we captured it in the constructor of the component
const graphqldata = await API.graphql(graphqlOperation(GetTournament, { id: this.state.itemId }));
console.log('graphqldata:', graphqldata);
// this is a bad way to access state after it has been set,
// state is asynchronous and takes time to set.
// You would need to access set by using the callback method
// this.setState({ singletour: graphqldata.data.getTournament });
// console.log('singletour:', this.state.singletour); // <- you should never do this after you setState
// this is how you should access state after you have set it
// this will guarantee that the state has been set before the
// console.log is called, so it should show the correct value of state
this.setState({
singletour: graphqldata.data.getTournament,
loaded: true // we are going to use the loaded value to handle our render
}, () => console.log('singletour:', this.state.singletour));
} catch (err) {
console.log('error: ', err);
// you may want to show an error message on the screen.
}
}
render () {
// access the passed parameters from state
const { itemId, otherParam, loaded, singletour } = this.state;
if (loaded) {
// if once the data is loaded we can show screen
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>
<Text>singletour: {JSON.stringify(singletour)}</Text>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
} else {
// while we are waiting for the data to load we could show a placeholder screen
// or we could show null. The choice is yours.
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Data not loaded</Text>
</View>
);
}
}
}
请注意,第一个渲染发生后componentDidMount
被调用,这就是为什么我们在state
中具有loaded
值的原因。通过使用loaded
,它允许我们处理给用户提供的内容,而不是在数据尚未完成加载的情况下呈现屏幕。
这显然是您代码的一种可能的重构。还有许多其他方法可以重构。
这里有一些关于设置状态的精彩文章
- https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0
- https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296
- https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6