API requests in svelte

Viewed 5113

I'm a bit new to svelte and javascript. I'm trying to build a page with many API components from external websites and I struggle a bit. I don't really know where to put the different bits of code. The closer I am no is this :

in Bapi.svelte (component) :

<script>

    function getSomething() {
        fetch('getapi')
    }
</script>

<h1>get something here</h1>
<button on:click={getSomething}>Get !</button>

in server.js (routes) :

import sirv from 'sirv';
import express from 'express';
import compression from 'compression';
import * as sapper from '@sapper/server';

const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';

const app = express();

app.use(express.urlencoded())
app.use(express.json())

    app.use(
        compression({ threshold: 0 }),
        sirv('static', { dev }),
        sapper.middleware()
    )
    .listen(PORT, err => {
        if (err) console.log('error', err);
});

in getapi.js (routes) :

export function get(res, req, next) {
    var resp = app.endpoints.coinbasepro.get('/coinbase-products');
    console.log(resp)
}

When I click on get i have this error : app is not defined. I maybe has something to do with the scope but after moving the variable around for a while I need some help because I am stuck at this point. Thanks

3 Answers

Well, as you are using sapper, it works a bit differently than when using pure svelte.

Your code runs on the client as well as on the server, but you only have access to fetch in the client code (it runs only in the browser). To circumvent this, you have access to this.fetch. So what you should do is use the preload function in a context module, passing the result to the component who needs it.

// Bapi.svelte
<script context="module">
  export async function preload() {
    const res = await this.fetch(`getapi`, {
        credentials: 'include'
    });

    // ...
    // Pass the api result to your component
      return { data: res }
    }
</script>

// This is your component, it lives in the same file
<script>
// You can get the data from the context module here
export let data
</script>

Context module and component are declared in the same file, but the context is not part of the component itself, the code in it runs before the component is created. You may have to use JSON.stringify(res) on the result, depending how it is structured.

Your main problem seems to be in the server as pointed out by @ThomasHennes, nothing directly to do with svelte or sapper.

I also believe you're not posting the complete code to continue helping you in this regard.


Leaving that aside, you still have a problem in your Svelte component, it is not Sapper-compatible, you cannot use fetch inside the script of the component, as pointed out by @Gh05d, because when the server is rendering, that code will run in NodeJs, and NodeJs does not have fetch.


This is the sapper-compatible version of your Svelte component

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

    let getSomething;
    onMount(()=>{
        getSomething = () =>{
            fetch('getapi')
        }
    });
</script>

<h1>get something here</h1>
<button on:click={getSomething}>Get !</button>

Any code you put inside the onMount will be executed only in the browser.

Thanks to you all for your answers ! I was using the wrong url to get the api so it wasn't helping. Eventually I used this code that worked fine for me :

in getapi.js

import Axios from "axios"
export async function get(res, req, next) {
     var resp = await Axios.get("https://api.pro.coinbase.com/products");
    console.log(resp)
}

in Bapi.svelte

<script>
    import {get} from "./getapi.js"
    function getSomething() {
        get()
        
    }
</script>

<h1>get something here</h1>
<button on:click={getSomething}>Get !</button>

and I moved getapi.js from routes to components I think it was creating a problem (but not sure)

Now I'm trying to get data from a websocket instead of the api, do you know a good crashcourse or tutorial on how to do that in svelte ?

Cheers all !!

Related