'Async Axios call not executed in Svelte: trying to use the result raises a TypeError: Cannot convert undefined or null to object ; Fetch API working
Summary
Context
Actual behavior (Problem)
Expected behavior
Minimal, Testable, Executable Example
Data
Sources
Notes
Clues
Context
I am trying to get a list of JSON objects from the URL http://localhost:1337/restaurants using Axios, in a Svelt Webapp. This call is censed to be executed when the Svelte component is initialized, similarly to the Svelte tutorial: https://svelte.dev/tutorial/await-blocks.
Actual behavior (Problem)
When I open the Web page containing the Svelte component, I don't see the network call in my Chromium dev tools network panel.
I can see this error shown in the Web page (obviously thanks to my {:catch}):
TypeError: Cannot convert undefined or null to object
Expected behavior
When I open the Web page containing the Svelte component, I should see the network call in my Chromium dev tools network panel, and it should show each of the JSON objects in a list item.
Of course, the following error must not be raised:
TypeError: Cannot convert undefined or null to object
Minimal, Testable, Executable Example
Data
This example uses the (Strapi) URL http://localhost:1337/restaurants, which returns the following array of JSON objects:
[{"id":1,"name":"Biscotte Restaurant","description":"Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.","published_at":"2021-10-02T20:04:26.780Z","created_at":"2021-10-02T19:40:30.378Z","updated_at":"2021-10-02T20:04:26.816Z","categories":[{"id":2,"name":"Brunch","published_at":"2021-10-02T20:04:03.395Z","created_at":"2021-10-02T19:41:15.186Z","updated_at":"2021-10-02T20:04:03.437Z"}]}]
Sources
<script>
import axios from 'axios';
async function getRestaurants() {
return await axios.get('http://localhost:1337/restaurants');
}
let restaurants_promise = getRestaurants();
</script>
<main>
{#await restaurants_promise}
<p>wait...</p>
{:then restaurants}
<p>The restaurants are:</p>
{#each restaurants.data as restaurant}
<li>
{restaurant.name}
</li>
{/each}
{:catch error}
<p style="color: red">{error}</p>
{/await}
</main>
Notes
I don't want to use Strapi's tutorialonMount and then/catch blocks as I prefer to follow the Svelte's tutorial (see the Strapi's tutorial: the Strapi tutorial) ("Strapi" because in fact http://localhost:1337/restaurants is a Strapi URL). I really try to stick to https://svelte.dev/tutorial/await-blocks.
Clues
With Postman, I can actually get the URL list of JSON objects so the network call works. So what is buggy is clearly my Svelte code.
With the Fetch API instead of Axios, my code works. I don't see anymore the error "TypeError: Cannot convert undefined or null to object".
Solution 1:[1]
There seems to be an error in the code that merges the user's config with the defaultConfig of axios (somehow the defaultConfig is undefined).
This issue was introduced in v0.21.2 so downgrading to latest v0.21.1 should work for the time being.
Solution 2:[2]
I've seen Svelte throw weird errors using an #each within an #await block. I solved this by adding an {#if} before the {#each}
<main>
{#await restaurants_promise}
<p>wait...</p>
{:then restaurants}
<p>The restaurants are:</p>
{#if restaurants.data}
{#each restaurants.data as restaurant}
<li>
{restaurant.name}
</li>
{/each}
{/if}
{:catch error}
<p style="color: red">{error}</p>
{/await}
</main>
Solution 3:[3]
This bug was fixed in Axios v0.26.1 (Changelog is here)
Solution 4:[4]
It looks like you just need to await the actual data. Right now you're awaiting the call and then trying to iterate over the data.
<script>
import axios from 'axios';
async function getRestaurants() {
const res = await axios.get('http://localhost:1337/restaurants');
const data = await res.data
return data
}
let restaurants_promise = getRestaurants();
</script>
<main>
{#await restaurants_promise}
<p>wait...</p>
{:then restaurants}
<p>The restaurants are:</p>
{#each restaurants as restaurant}
<li>
{restaurant.name}
</li>
{/each}
{:catch error}
<p style="color: red">{error}</p>
{/await}
</main>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Stephane Vanraes |
| Solution 2 | |
| Solution 3 | GAMELASTER |
| Solution 4 | JHeth |
