why context is undefined in svelte
Asked Answered
M

3

6

I'm working on a component and i need to use context for it. But i don't know why when i using getContext, It's undefined.

This is a part of my codes on first component (Index Component):

import { setContext } from 'svelte';
import {onMount} from "svelte";

let tempSuggest;

const suggestModel = {
   category_id: 1,
   title: "",
   images: [{}],
   catalogues: [{}],
   dependent_attributes: [{}],
   independent_attributes: [{}],
};

$: tempSuggest = Object.assign({}, suggestModel);

onMount(() => {
   setContext(clientProductSuggest, tempSuggest);
});

In html codes of first component (loading sub components in the end of index file):

<svelte:component this={component} {...props}/>

In second component:

import { getContext } from 'svelte';
const c = getContext('clientProductSuggest');

console.log(c);

And now context is undefined.

Monarch answered 3/8, 2020 at 9:22 Comment(0)
A
11

It's not probably not going to cover this question but keep in mind that getContext is only gonna work for children of the setContext component.

For cross-component sharing we should use stores.

I am writing this answer because if I had found it here, it would have saved me a few hours of research and posting to the svelte community chat.

Amphipod answered 6/9, 2021 at 7:14 Comment(0)
F
1

This is because contexts in Svelte are not reactive by default, when you assign tempSuggests to the context it is in fact undefined

In order to get reactivity in your context you should create tempSuggests as a store:

import { setContext } from 'svelte';
import { writable } from "svelte/store";

let tempSuggest = writable({});

const suggestModel = {
   category_id: 1,
   title: "",
   images: [{}],
   catalogues: [{}],
   dependent_attributes: [{}],
   independent_attributes: [{}],
};

$: tempSuggest.update(value => Object.assign(value, suggestModel));
setContext('clientProductSuggest', tempSuggest);

Also consider the following:

  • setContext does not have to be called inside onMount
  • the first argument of setContext should be a string (I added '')
  • suggestModel is now a store and should be treated as such in the children
Forsaken answered 3/8, 2020 at 11:23 Comment(3)
I have used your code, But why when i log the context in console after setContext, In get method doesn't show to me the suggestModel?Monarch
I wanna to make my temporary variable empty and looklike as suggestModel, when pages load or when user presses the cancel button, then context needs to be updated.Monarch
When you say "log the context after setContext" is that in the child, immediately after doing getContext ? Because at that point you have not updated the tempSuggest yetForsaken
F
0

Yes you can make it a store to make it have the right value but in fact that's just working around the initial problem :

I don't know why but reactive statements/blocks are executed only at the end of component initilization. So the real order of execution is :

import { setContext } from 'svelte';
import {onMount} from "svelte";

let tempSuggest;

const suggestModel = {
   category_id: 1,
   title: "",
   images: [{}],
   catalogues: [{}],
   dependent_attributes: [{}],
   independent_attributes: [{}],
};

setContext("clientProductSuggest", tempSuggest);

$: tempSuggest = Object.assign({}, suggestModel);

... and now it makes sense.

I have no idea why this is the case. Bute here the docs indeed state : Reactive statements run after other script code and before the component markup is rendered

If you want to play around: https://svelte.dev/repl/6ba4692567754a8f8e3499a3ed38edf3?version=3.59.1

Foppery answered 10/5, 2023 at 11:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.