In my app I type in a string, which is then immediately invoked in rest api call and json object is returned containing all drinks according to the name typed in. Then I would like to display a specific part of that object, for example the name, but I get undefined error when accesssing that part of the object, which I will elaborate later. I am implementing react-navigation and react-elements and variables are refreshed by hooks.
export default class App extends Component {
render() {
console.log('change')
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
}
The problem is in Home, my code works as far as displaying full object after each typed character: I can display object of all the drinks containing queried name that I typed in. But then, I want to display a specific element in the object, for example the first id (object.drinks[0].idDrink), which I assume doesnt load up yet and there comes the undefined error. I could access the id before when doing things without hooks, that part is not wrong. I assume I broke things implementing many hooks that are refreshing my app.
function HomeScreen() {
const [query, setQuery] = useState('');
const [jsonData, setJsonData] = useState([]);
const [loading, setLoading] = useState(true);
console.log(loading, '1')
useEffect(() => {
setLoading(true);
console.log(loading, '2')
fetch('https://www.thecocktaildb.com/api/json/v1/1/search.php?s=' + query, {
method: 'GET',
})
.then(response => response.json())
.then(jsonD => setJsonData(jsonD),
setLoading(false),
console.log(loading, '3'))
.catch(error => {
console.error(error);
});
}, [query])
return (
<ScrollView >
<Text>Bartender</Text>
<SearchBar
placeholder="Type Here..."
onChangeText={setQuery}
value={query}
/>
<>
{
loading ? console.log('waiting for loading') : console.log(jsonData.drinks[0].idDrink)
}
</>
</ScrollView >
);
}
I tried to fix the problem by setting loading variable, which would render the object after it is fully loaded, but it does not fix it.
If I run the app displaying console log instead of specific element:
loading ? console.log('waiting for loading') : console.log('the data should be loaded'),
this is the output:
[Thu Dec 17 2020 20:20:07.902] LOG change
[Thu Dec 17 2020 20:20:08.159] LOG true 1
[Thu Dec 17 2020 20:20:08.175] LOG waiting for loading
[Thu Dec 17 2020 20:20:13.218] LOG true 2
[Thu Dec 17 2020 20:20:13.284] LOG true 3
[Thu Dec 17 2020 20:20:13.451] LOG false 1
[Thu Dec 17 2020 20:20:13.486] LOG the data should be loaded
[Thu Dec 17 2020 20:20:14.761] LOG false 1
[Thu Dec 17 2020 20:20:14.775] LOG the data should be loaded
after I type a character in the search bar, the output is:
[Thu Dec 17 2020 20:23:54.892] LOG false 1
[Thu Dec 17 2020 20:23:54.938] LOG the data should be loaded
[Thu Dec 17 2020 20:23:55.526] LOG false 2
[Thu Dec 17 2020 20:23:55.781] LOG false 3
[Thu Dec 17 2020 20:23:55.807] LOG false 1
[Thu Dec 17 2020 20:23:55.840] LOG the data should be loaded
[Thu Dec 17 2020 20:23:56.294] LOG false 1
[Thu Dec 17 2020 20:23:56.312] LOG the data should be loaded
TLDR: How do I make sure that I access the object refreshed by hooks after it is fully loaded?

jsonD => setJsonData(jsonD), setLoading(false), console.log(loading, '3')isn't valid, there should be a function body. React state updates are also asynchronous, so you can'tconsole.log(loading, '2')right aftersetLoading(true);and expect it to log the state just enqueued.loadingstate, conditionally renderjsonDatawhen it is populated. Also, it may help to keep your state consistently typed, i.e. initial state ofjsonDatais an empty array but your UI code accesses as if it were an object. The array obviously won't ever have adrinksproperty to access an array index of.