Jay
Jay

Reputation: 39

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 >;

Upvotes: 1

Views: 1226

Answers (1)

snnsnn
snnsnn

Reputation: 13698

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 '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

Upvotes: 1

Related Questions