使用SolidJS上下文在异步函数中

huangapple go评论46阅读模式
英文:

Using SolidJS context in async function

问题

以下是您要求的翻译:

"Is it possible to get the context value in an async function called from a component?
Even runWithOwner() gives me the default value of the context, not the enclosing value, after the first await.

  const Ctx = createContext('default');
  return <Ctx.Provider value='not-default' >{
    (() => {
      runWithOwner(getOwner()!, async () => {
        const f = async () => {};
        console.log('before', useContext(Ctx));
        await f();
        console.log('after', useContext(Ctx));
      });
      return '';
    })()
  }</Ctx.Provider >;

Tried enclosing the async call in runWithOwner()
Update: I 'solved' it by using signals instead of context. It's an import of a global variable either way, but signals work...

  const [Sig, setSig] = createSignal('default');
  const Ctx = createContext('default');
  const f = async (where: string) => {
    console.log(where, 'ctx', useContext(Ctx), 'sig', Sig());
  };
  return <Ctx.Provider value={setSig('not-default')} >{
    (() => {
      (async () => {
        await f('first');
        await f('broken');
      })();
      return '';
    })()
  }</Ctx.Provider >;
```"

<details>
<summary>英文:</summary>

Is it possible to get the context value in an async function called from a component?

Even runWithOwner() gives me the default value of the context, not the enclosing value, after the first await.

```typescript
  const Ctx = createContext(&#39;default&#39;);
  return &lt;Ctx.Provider value={&#39;not-default&#39;} &gt;{
    (() =&gt; {
      runWithOwner(getOwner()!, async () =&gt; {
        const f = async () =&gt; {};
        console.log(&#39;before&#39;, useContext(Ctx));
        await f();
        console.log(&#39;after&#39;, useContext(Ctx));
      });
      return &#39;&#39;;
    })()
  }&lt;/Ctx.Provider &gt;;

Tried enclosing the async call in runWithOwner()

Update: I 'solved' it by using signals instead of context. It's an import of a global variable either way, but signals work...

  const [Sig, setSig] = createSignal(&#39;default&#39;);
  const Ctx = createContext(&#39;default&#39;);
  const f = async (where: string) =&gt; {
    console.log(where, &#39;ctx&#39;, useContext(Ctx), &#39;sig&#39;, Sig());
  };
  return &lt;Ctx.Provider value={setSig(&#39;not-default&#39;)} &gt;{
    (() =&gt; {
      (async () =&gt; {
        await f(&#39;first&#39;);
        await f(&#39;broken&#39;);
      })();
      return &#39;&#39;;
    })()
  }&lt;/Ctx.Provider &gt;;

答案1

得分: 1

上下文值不是一个信号,而是一个驻留在当前所有者上的对象属性,因此在异步函数中访问它不是一个问题,也不需要 runWithOwner

问题在于你在通过 Ctx.Provider 设置新值之前,在异步作用域内捕获了该值。尝试通过一个变量来访问它,你将获得更新后的值。

import { createContext, useContext } from 'solid-js';
import { render } from 'solid-js/web';

const Ctx = createContext('default');

const Comp = () => {
  const cxt = useContext(Ctx);
  const run = () => {
    setTimeout(() => console.log(cxt), 1000);
    return null;
  }
  return run();
};

export const App = () => {
  return (
    <Ctx.Provider value='not-default' >
      <div>{useContext(Ctx)}</div>
      <Comp />
    </Ctx.Provider>
  );
};

render(() => <App />, document.body);

https://playground.solidjs.com/anonymous/ab5ca23c-9551-416e-8e37-ef2c50d20ab1

英文:

Context value is not a signal but an object property that resides on the current owner, so accessing it in an async function is not a problem and does not require runWithOwner.

The problem is you are capturing the value inside an async scope before setting a new value through Ctx.Provider. Try accessing it through a variable, you will get the updated value.

import { createContext, useContext } from &#39;solid-js&#39;;
import { render } from &#39;solid-js/web&#39;;

const Ctx = createContext(&#39;default&#39;);

const Comp = () =&gt; {
  const cxt = useContext(Ctx);
  const run = () =&gt; {
    setTimeout(() =&gt; console.log(cxt), 1000);
    return null;
  }
  return run();
};

export const App = () =&gt; {
  return (
    &lt;Ctx.Provider value={&#39;not-default&#39;} &gt;
      &lt;div&gt;{useContext(Ctx)}&lt;/div&gt;
      &lt;Comp /&gt;
    &lt;/Ctx.Provider&gt;
  );
};

render(() =&gt; &lt;App /&gt;, document.body);

https://playground.solidjs.com/anonymous/ab5ca23c-9551-416e-8e37-ef2c50d20ab1

huangapple
  • 本文由 发表于 2023年3月7日 07:48:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75656845.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定