Why doesn't my fetch POST function work in Svelte?

Viewed 1936

I have a Svelte application that is supposed to perform CRUD operations with a local JSON file via the Fetch API.

The "GET" operations works as intended but when I tried to create the "POST" function, I got the below error message:

Uncaught (in promise) Error: {#each} only iterates over array-like objects.
    at validate_each_argument (index.mjs:1977)
    at Object.update [as p] (index.svelte? [sm]:33)
    at update (index.mjs:1057)
    at flush (index.mjs:1025)

Below is the code in index.svelte:

<script>
    import { onMount } from 'svelte';

    let data1 = '';
    onMount(async function () {
        const data = await (await fetch('http://localhost:5000/data1')).json();
        data1 = data;
        console.log(data);
    });
    const createData1 = async () => {
        const data =
            (await fetch('http://localhost:5000/data1'),
            {
                method: 'Post',
                body: JSON.stringify({
                    id: data1.length + 1,
                    text: '',
                }),
                headers: {
                    'Content-Type': 'application/json'
                }
            });
        data1 = data;
        console.log(data);
    };
</script>

<div style="display: grid; place-items:center;">
    <div class="horizontal">
        {#each data1 as d1}
            <div contenteditable="true">{d1.text}</div>
        {/each}
        <button type="submit" on:click|preventDefault={createData1}>+</button>
    </div>
</div>

And below is the contents of the JSON file:

{
    "data1": [
        {
            "id": 1,
            "text": "blabla",
        },
        {
            "id": 2,
            "text": "bla bla",
        }
    ]
}

Why isn't the the object being created? It is inside an array after all.

2 Answers

As your log shows, data is an object, not an array. data.captions is the array you want to iterate over.

So you'll want to slightly modify your createData method near the end:

    const createData1 = async () => {
        ...
        // data1 = data;
        data1 = data.data1;
        console.log(data);
    };

It looks to me like you need to adjust your code syntax a bit and make sure you convert your response to JSON and you will be in business. This should work:

const data = (await fetch('http://localhost:5000/data1', {
  method: "POST",
  body: JSON.stringify({
    id: data1.length + 1,
    text: ''
  }),
  headers: {
    "content-type": "application/json"
  }
})).json();
data1 = data;

The notable adjustments are:

  • Use the fetch overload that takes first argument as URL and the second argument as the request options object (Looks like this is what you were after and an extra "(" character was throwing it of)
  • Make sure to convert the result of the POST call to JSON. Your "GET" request does this conversion and you get what you are expecting.
Related