I'm a bit new to svelte and javascript. I'm trying to build a page with many API ponents 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 (ponent) :
<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 pression from 'pression';
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(
pression({ 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
I'm a bit new to svelte and javascript. I'm trying to build a page with many API ponents 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 (ponent) :
<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 pression from 'pression';
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(
pression({ 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
Share Improve this question asked Jul 22, 2020 at 22:56 James ChenJames Chen 891 silver badge9 bronze badges 1-
3
The
app
variable is only defined withinserver.js
. You would have to explicitly export it from there and import it where needed in your server routes before you can make use of it. On top of that, I don't see theendpoints.coinbasepro.get()
method you're trying to access on theapp
object defined anywhere. Where is it ing from? – Thomas Hennes Commented Jul 23, 2020 at 2:16
3 Answers
Reset to default 2Well, 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 ponent 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 ponent
return { data: res }
}
</script>
// This is your ponent, it lives in the same file
<script>
// You can get the data from the context module here
export let data
</script>
Context module and ponent are declared in the same file, but the context is not part of the ponent itself, the code in it runs before the ponent 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 plete code to continue helping you in this regard.
Leaving that aside, you still have a problem in your Svelte ponent, it is not Sapper-patible, you cannot use fetch inside the script of the ponent, 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-patible version of your Svelte ponent
<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./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 ponents 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 !!