Skip to content

[✨] support qwik functions(use*) after async callsites(await...) #99

@revintec

Description

@revintec

in version 0.18.1, latest version as of writing, we can't use qwik functions(use*) after await
this limitation is here to because when qwik functions are called, a proper executionContext must be recoverable

but it's an implementation detail and it makes qwik harder to use, requires more boilerplate code(useSignal<...>(...), useTask$(async...), if(!signal.value)return, etc.) when async callsites are involved

I propose a way to solve this, in 2 steps

  1. implements const restoreEnv=useCallsite() or const restoreEnv=useAsync() by
    function useCallsite(){const ctxt=tryGetInvokeContext();return()=>void(_context=ctxt);}
    I actually appended export const USE_CONTEXT=()=>{const ctxt=_context;return()=>_context=ctxt} to core.mjs for testing, and currently found no major problems. there're however some edge cases and warnings

then users can use it like this:

  component$(async(...)=>{
    ...
    const restoreEnv=USE_CONTEXT()
    await ...
    restoreEnv()
    ...
    useSignal(...)
    ...
  }
  1. in the future, the qwik compiler should be able to detect await callsites, and add restoreEnv(...) automatically
    but this is tricky so we can implement 1 first, which should be easier to implement and reason about

original POST follows

Is your feature request related to a problem?

currently code like export default component$(async()=>...) would compile and work fine
notice the async there. but vscode is reporting syntax error

Argument of type '() => Promise<JSXNode<any> | null>' is not assignable to parameter of type 'OnRenderFn<{}>'.
  Type 'Promise<JSXNode<any> | null>' is missing the following properties from type 'JSXNode<any>': type, props, key
ts(2345)

Describe the solution you'd like

can we modify https://github.com/BuilderIO/qwik/blob/70880b71995361202ae0b4725454cb2bd008ab2d/packages/qwik/src/core/component/component.public.ts to update the component$ signature?

from export type OnRenderFn<PROPS> = (props: PROPS) => JSXNode<any> | null
to export type OnRenderFn<PROPS> = (props: PROPS) => ValueOrPromise<JSXNode<any> | null>

it's a small change but I don't know if it's acceptable/compatible/safe

Describe alternatives you've considered

export default component$(()=><>{(async()=>...)()}</>)

but that's ugly and verbose

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions