Svelte: Incorrect context in child component inside await

Created on 20 Apr 2019  路  6Comments  路  Source: sveltejs/svelte

bug

Most helpful comment

Naive fix:

diff --git a/src/runtime/internal/await_block.ts b/src/runtime/internal/await_block.ts
index 3834ff7c..14f68d5c 100644
--- a/src/runtime/internal/await_block.ts
+++ b/src/runtime/internal/await_block.ts
@@ -1,4 +1,5 @@
 import { assign, is_promise } from './utils';
+import { get_current_component, set_current_component } from './lifecycle';
 import { check_outros, group_outros, transition_in, transition_out } from './transitions';
 import { flush } from './scheduler';

@@ -40,9 +41,12 @@ export function handle_promise(promise, info) {
    }

    if (is_promise(promise)) {
+       const current_component = get_current_component();
        promise.then(value => {
+           set_current_component(current_component);
            update(info.then, 1, info.value, value);
        }, error => {
+           set_current_component(current_component);
            update(info.catch, 2, info.error, error);
        });

diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts
index d659fd2e..0ca3e430 100644
--- a/src/runtime/internal/lifecycle.ts
+++ b/src/runtime/internal/lifecycle.ts
@@ -6,7 +6,7 @@ export function set_current_component(component) {
    current_component = component;
 }

-function get_current_component() {
+export function get_current_component() {
    if (!current_component) throw new Error(`Function called outside component initialization`);
    return current_component;
 }

This doesn't break any existing tests, and at first glance seems to fix the issue here. I have no idea whether this is a good idea.

All 6 comments

@EmilTholin This issue is biting me when trying to use the {#await ...} block to render a <Link> component from your svelte-routing. It only happens if the route with async <Link> is the initial one to load. If you transition to the route via another link, it doesn't have this issue as the Route isn't in init, it is in flush.

I thought about raising this in svelte-routing (and let me know if I still should), but it is directly related to this context/current_component issue.

Is there any known workaround to this issue other than simply not using context at all?

I'd argue that not using {#await} is a more viable workaround. Context lets you do things not otherwise possible, while {#await} is mostly a convenience over updating certain bits of state when a promise stored in another variable resolves or rejects.

Naive fix:

diff --git a/src/runtime/internal/await_block.ts b/src/runtime/internal/await_block.ts
index 3834ff7c..14f68d5c 100644
--- a/src/runtime/internal/await_block.ts
+++ b/src/runtime/internal/await_block.ts
@@ -1,4 +1,5 @@
 import { assign, is_promise } from './utils';
+import { get_current_component, set_current_component } from './lifecycle';
 import { check_outros, group_outros, transition_in, transition_out } from './transitions';
 import { flush } from './scheduler';

@@ -40,9 +41,12 @@ export function handle_promise(promise, info) {
    }

    if (is_promise(promise)) {
+       const current_component = get_current_component();
        promise.then(value => {
+           set_current_component(current_component);
            update(info.then, 1, info.value, value);
        }, error => {
+           set_current_component(current_component);
            update(info.catch, 2, info.error, error);
        });

diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts
index d659fd2e..0ca3e430 100644
--- a/src/runtime/internal/lifecycle.ts
+++ b/src/runtime/internal/lifecycle.ts
@@ -6,7 +6,7 @@ export function set_current_component(component) {
    current_component = component;
 }

-function get_current_component() {
+export function get_current_component() {
    if (!current_component) throw new Error(`Function called outside component initialization`);
    return current_component;
 }

This doesn't break any existing tests, and at first glance seems to fix the issue here. I have no idea whether this is a good idea.

Fixed in 3.9.1, thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thoughtspile picture thoughtspile  路  3Comments

noypiscripter picture noypiscripter  路  3Comments

robnagler picture robnagler  路  3Comments

1u0n picture 1u0n  路  3Comments

mmjmanders picture mmjmanders  路  3Comments