@urql/svelte - Function called outside component initialization

1.6k Views Asked by At

I'm trying to integrate graphQL API using @urql/svelte in svelte. I have to call the graphQL query on the button click. But when I do that, I get following error:

Uncaught (in promise) Error: Function called outside component initialization
    at get_current_component (index.mjs:948:15)
    at getContext (index.mjs:981:12)
    at getClient (context.ts:7:14)
    at query (operations.ts:58:18)
    at getNonce (metamask.ts:27:2)
    at loadData (index.svelte? [sm]:28:17)

I have initialised connection in __layout.svelte.

    initClient({
        url: "http://localhost:8082/graphql",
        fetchOptions: {
            headers: {
                authorization: "xxxxxxxxxx"
            }
        }
    });

Following is the myquery.ts file where query is defined:

import { operationStore, query } from '@urql/svelte';
const nonceQuery = `
   query ($address: String!) {
       nonceQuery(address: $address) {
           nonce
       }
   }
`;
export const getNonce  = (address: string) => {
    const nonce = operationStore(nonceQuery,
        { address }
    );
    query(nonce);
    return nonce;
};

And in index.svelte file I'm trying to call this on button click:

<script>
 import { getNonce } from "./myquery";
 let nonce;

 const onCall = () => {
   nonce = getNonce("some_address")
 }

 $: console.log("nonce: ", $nonce)
</script>

<button on:click={onCall}>
  Nonce
</button>


1

There are 1 best solutions below

1
On

From the stack trace you can see that getContext was called at some point, which is not allowed outside of the component initialization as noted by the error message (though that message could mention that this is about getContext...).

You might need to rewrite the functions in a way that they no longer rely on getting a context internally. You could either pass the required object as an argument or possibly construct a sort of API class first, that gets the context during initialization but does not load any data yet.

Example:

class Api {
    constructor() {
        this.client = getContext('client');
    }
    
    load() {
        // Use client here
        console.log(this.client);
    }
}

// Construct during component init, use later
const api = new Api();

function onButtonClick() {
    api.load();
}

Extended REPL