Мне кажется, я знаю, что вы пытаетесь сделать, и этого можно добиться с помощью рефакторинга вашего кода.
Вот что я бы сделал:
- Захватите вашпараметры навигации в
constructor
вашего компонента и сохраните их в state
. - Установите начальное значение для SingleTour в состоянии.Установите значение для
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
вызывается после первого рендеринга, поэтому у нас есть значение loaded
в state
,Использование loaded
позволяет нам обрабатывать то, что представляется пользователю, а не отображать экран, на котором данные еще не закончили загружаться.
Это, безусловно, один из возможных рефакторингов вашего кода.Есть много других способов его рефакторинга.
Вот несколько замечательных статей о настройке состояния