Interacting with APIs in Svelte applications

I'm fairly new to utilizing Svelte and JavaScript. I've been attempting to construct a page that incorporates numerous API components from external websites, but I'm facing some challenges. I'm uncertain about where exactly to place the various sections of code. The closest solution I have managed to come up with is as follows:

Inside Bapi.svelte (component):

<script>

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

<h1>retrieve data here</h1>
<button on:click={getSomething}>Get Data!</button>

Inside 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);
});

Inside getapi.js (routes):

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

Upon clicking 'Get Data', I encounter this error: "app is not defined". This issue might be related to scope, but after shuffling the variable around for some time, I find myself in need of assistance as I am currently stuck at this stage. Thank you.

Answer №1

When working with sapper, the approach differs from using pure svelte.

Your code is executed on both the client and server, but you are limited to using fetch only in the client code (which runs in the browser). To address this limitation, you can utilize this.fetch. Therefore, it is recommended to employ the preload function in a context module and pass the result to the relevant component.

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

    // Pass API data to the component
      return { responseData: response }
    }
</script>

// Component where the data will be used
<script>
// Accessing the data from the context module
export let responseData
</script>

The context module and component reside in the same file, but the context operates independently from the component itself. The context's code executes before the component creation. Depending on how the data is structured, you may need to use JSON.stringify(response) on the fetched result.

Answer №2

It appears that the issue lies within your server, as noted by @ThomasHennes, rather than being directly related to svelte or sapper.

Furthermore, it seems like you haven't provided the complete code for us to offer further assistance.


Setting those concerns aside, there is an issue with your Svelte component – it is not compatible with Sapper. The use of fetch within the script of the component, as mentioned by @Gh05d, is problematic because this code will run in NodeJs during server-side rendering where fetch is not available.


Below is a version of your Svelte component that is compatible with Sapper:

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

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

Remember, any code inside the onMount function will only execute in the browser.

Answer №3

Thank you everyone for your help with this! I discovered that my issue was using the incorrect URL for the API, which was causing the problem. I ended up using this code successfully:

Inside 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>Retrieve something here</h1>
<button on:click={getSomething}>Get !</button>

I also relocated getapi.js from routes to components as I believed it may have been causing an issue (though not confirmed)

Currently, I am exploring consuming data from a websocket rather than an API. Do any of you know of a good crash course or tutorial on how to achieve this in Svelte?

Cheers to all!!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can an array be generated on-the-fly with objects contained within it?

Seeking advice on looping through an array of objects to achieve a specific result. Here is the initial array: var testArray = [{'name':'name1', 'xaxis':'xaxis1', 'yaxis':'yaxis1'}, ...

Differences between importing {fn1} from 'lib' and importing fn1 from 'lib'

When it comes to importing functions from lodash, I have been advised by my coworker that it is more efficient to import each function individually rather than as a group. The current method of importing: import {fn1, fn2, fn3} from 'lodash'; ...

Revamp the style of the date field in a Material UI dialog

I'm currently working on a React project where I am using Material-UI's date picker component to display date items. However, I find that the default style does not meet my requirements. I would like to use a selector for displaying dates in the ...

jQuery floating sidebar that dynamically adjusts position based on content overflow

I've come across an interesting scenario with a fiddle that I'm working on: http://jsfiddle.net/yFjtt/1/ The main concept is to allow users to scroll past the header and have the sidebar 'stick' in place as they continue scrolling down ...

Adjust the size of every card in a row when one card is resized

At the top of the page, I have four cards that are visible. Each card's height adjusts based on its content and will resize when the window size is changed. My goal is to ensure that all cards in the same row have equal heights. To see a demo, visit: ...

Enhancing MEAN Stack Application by Updating Table Post Database Collection Modification

In my efforts to ensure that my table data remains synchronized with the database information, I have encountered an issue. Whenever Data Changes: $scope.changeStatus = function($event,label,status){ var target = $event.currentTarget; target ...

Arranging HTML elements using JavaScript or jQuery

Something seems off. The sorting doesn't work as expected. Check out the JavaScript code below: function sortDescending(a, b) { var date1 = $(a).data('date'); var date2 = $(b).data('date'); return date1 > date2; } ...

Executing the onSuccess callback in Ajax without any ability to manipulate the ajax requests

My dilemma lies in needing to execute a JavaScript function upon the successful completion of an AJAX call. Unfortunately, I am unable to directly manage the AJAX calls as they are handled by the DNN5 framework. Is there a way for me to trigger my functio ...

Creating a custom decision tree in Angular/JS/TypeScript: A step-by-step guide

My current project involves designing a user interface that enables users to develop a decision tree through drag-and-drop functionality. I am considering utilizing GoJS, as showcased in this sample: GoJS IVR Tree. However, I am facing challenges in figuri ...

Activate the JavaScript loader while data is being fetched

I'm currently working on incorporating a loader into my website that should remain visible throughout the entire loading process. For example, if the load time is around 6.8 seconds (with 6.3 seconds of waiting and 0.4 seconds of downloading), I want ...

You cannot directly access an array useState by index in React js, but you can use the map function to

export interface JobListing { id: number, isTraded: boolean, feedback: string, title: string, message: string, skills: string[], sender: string, ipAddress: string } const GroupList = () => { const [jobListings, setJobListings] = useSt ...

Is using debounce with $scope.$apply a logical choice?

In my experience, I have come across a method that claims to decrease the number of $digest loops by incorporating debouncing into the $scope.$apply process. It looks something like this: $scope.$apply = _.debounce($scope.$apply, 250); Is this approach v ...

Having trouble with updating your website asynchronously through code? In need of a detailed explanation?

Here are two Javascript functions that are used to call a python file in order to update an HTML page. The first function works perfectly fine, but the second one seems to be malfunctioning without throwing any errors. function button(key) { var xhttp ...

Using more than one class at a time is causing issues

Essentially, I have a div and I want to create an exercise where I apply three different classes using vue.js. I attempted to use v-bind:class, specifically :class, but can I bind a class directly from CSS? This is what I tried: html <div :style="[my ...

Executing a PHP function within the same file using AJAX: A step-by-step guide

I've been exploring online tutorials to learn about ajax as it's a new technology for me. My main goal is to understand how to utilize two functions, create() and population(), in a php file. The create() function generates a form like this: ma ...

WebSocket connection established on port 8888, while the web server is running on port 80 - incompatible to merge the two services

Here is some node.js server-side code that involves watching a file and sending modifications to the browser: var app = require('http').createServer(handler) , io = require('socket.io').listen(app) , fs = require('fs') a ...

The bootstrap modal is appearing correctly, but the content within it is not displaying properly

I've been working on a website and added a modal for signup. However, when the user clicks on the signup button, the modal appears but the content inside it is not clickable. Can someone please help me with this issue? Here is the code snippet I am us ...

Adjust the color of a selected edge in Three.js

let cubeEdges = new THREE.EdgesHelper(cube, 0xff0000); cubeEdges.material.linewidth = 5; scene.add(cubeEdges); A cube has been created using the following code: new THREE.Mesh(new THREE.BoxGeometry(200, 200, 200, 1, 1, 1, materials), new THREE.MeshFaceMa ...

Is there a way to determine if an element has been scrolled past?

I am currently working on a script to detect when a specific element comes into view while scrolling. const targetElement = document.getElementById('sidebar'); window.addEventListener('scroll', () => { if (window.scrollY > tar ...

Tips for utilizing the "this" keyword in JavaScript in conjunction with the change function

I'm currently facing an issue with the change function. I have two dropdowns that are dependent on each other. Whenever the first dropdown changes, it triggers a change in the second dropdown as well. I achieved this functionality using jQuery AJAX. H ...