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?
I recommend you to go about the problem differently.
Instead of making the default value of
jsonData
an array you could set the default value tonull
:This way you also don't need keep track of and update a
loading
state.The problem with the other approach as you've experienced is that you can't be sure that the
jsonData
state has been updated before theloading
state has.