qwik icon indicating copy to clipboard operation
qwik copied to clipboard

Context in Layouts

Open mastastealth opened this issue 2 years ago • 6 comments

Qwik Version

0.10.0

Operating System (or Browser)

W10 / Firefox

Node Version (if applicable)

No response

Which component is affected?

Qwik City

Expected Behaviour

I expected the consumption of a context to work fine within a route given a layout wrapped in a provider.

Actual Behaviour

I get the following error:

Code(13): Actual value for useContext() can not be found, make sure some ancestor component has set a value using useContextProvider()

Additional Information

I've pushed a fresh Qwik City install in an example repo, then applied the simplest version of my context changes, which reproduces the error I'm seeing.

Also worth mentioning, that using that same context from the Header component does work.

mastastealth avatar Oct 09 '22 01:10 mastastealth

This was implemented previously. Appears to be a regression.

https://github.com/BuilderIO/qwik/issues/599

nnelgxorz avatar Oct 09 '22 03:10 nnelgxorz

I get the same error when I try to use useContent() inside the default src/root.tsx layout component.

jrson83 avatar Oct 09 '22 04:10 jrson83

I would help a lot of simple piece of code that reproduces it, maybe in the playground https://qwik.builder.io/playground/

manucorporat avatar Oct 10 '22 07:10 manucorporat

Won't be able to reproduce in the playground because it needs a layout.tsx to trigger the bug.

@mastastealth has the minimal repro here https://github.com/mastastealth/qwik-context/commit/83d16aab40a88365e34e2ca7e030e77938b3c537

The important parts are src/routes/layout.tsx and src/components/my-context.tsx

nnelgxorz avatar Oct 10 '22 10:10 nnelgxorz

@manucorporat Here's the same repo example code on Stackblitz, if that is quicker.

mastastealth avatar Oct 11 '22 13:10 mastastealth

FYI I tested with 0.11.1 and 0.0.112 and the issue is still present

wmertens avatar Oct 17 '22 05:10 wmertens

Do we know which version was/will-be released this fix?

NachoVazquez avatar Nov 15 '22 15:11 NachoVazquez

@NachoVazquez should be fixed in 0.12 already I think, can you check with 0.13.3?

wmertens avatar Nov 15 '22 18:11 wmertens

The problem still exist in 0.13.3

mingfang avatar Nov 15 '22 18:11 mingfang

@wmertens Yes, I confirm like @mingfang that the error is still present in 0.13.3

NachoVazquez avatar Nov 15 '22 19:11 NachoVazquez

@mingfang @NachoVazquez Can one of you make a Stackblitz reproduction?

nnelgxorz avatar Nov 16 '22 20:11 nnelgxorz

In a second!

NachoVazquez avatar Nov 16 '22 20:11 NachoVazquez

@nnelgxorz This was created by a coworker of mine. I just updated the versions.

https://stackblitz.com/edit/qwik-starter-vyaj1q?file=src/routes/flower/index.tsx

Steps to reproduce:

  1. Click on the "Blow my mind 🤯 with a context error Code(13)" link.
  2. Check the console.

NachoVazquez avatar Nov 16 '22 20:11 NachoVazquez

@manucorporat confirmed. routes/layout.tsx has the contextprovider, and flower/index.tsx uses the context but has no access to it.

wmertens avatar Nov 17 '22 09:11 wmertens

Still in latest and it only happens when using the Link and doing client-side navigation if that helps.

jwickers avatar Nov 29 '22 04:11 jwickers

After bringing this bug up twice in the Discord server (I'm Data in Discord), I thought I would try to find a workaround for using Link in SPAs.

Steps when using the Stackblitz link:

Context works in Named Layouts always.

  • Start the app and click the Will context work in Named Layouts? button over and over.

Context won't work in normal Layouts the first attempt almost ever.

  • Restart the app and click the Will context work for a normal Layout? button immediately.

Context will work in normal Layouts AFTER running a Named Layout first.

  • Restart the app and click the Will context work for a Named Layouts? and then the Will context work for a normal Layout? button.

https://stackblitz.com/edit/qwik-starter-5xnz1q?file=src/routes/index.tsx

The workaround appears to be to use Named Layouts for now. Hope this helps!

T-travis avatar Nov 30 '22 05:11 T-travis

Is this bug still present? Because I am having it right now on version 0.16.2

Dindaleon avatar Jan 09 '23 03:01 Dindaleon

I found a temporal fix:

Write a component with the following:

import {
  component$,
  Slot,
  useClientEffect$,
  useContext,
} from '@builder.io/qwik'
import { AuthContext } from './authProvider'

export const ContextSetter = component$(() => {
  const auth = useContext(AuthContext)
  useClientEffect$(({ track }) => {
    track(auth)
  })

  return <Slot></Slot>
})

In root.tsx put the component inside the body tags

<body lang="en">
  <ContextSetter>
    <RouterOutlet />
    <ServiceWorkerRegister />
  </ContextSetter>
</body>

It works like a charm. Waiting for an official fix :)

Dindaleon avatar Jan 12 '23 18:01 Dindaleon

Bug is still present. And temporal fix not work. Ok, from parent to child it works (without the temporal fix). But not from child to parent. Or how I have to pass data from child to parent. Or what is the correct way to handle this: User input from component a is imported in component c. User input is processed in component b and is imported in the layout.tsx.

frankroc2022 avatar May 23 '23 17:05 frankroc2022

I know this issue is closed but if someone comes across it. The issue seems to be able to be resolved my using the 'useContextProvider' in Layout instead of having a component that wraps around.

Like if you had 'MyContextProvider' and used it in your layout.tsx

layout.tsx

<MyContextProvider>
</MyContextProvider>

imMadsen avatar Apr 12 '24 10:04 imMadsen

Okay, I think I might have a good solution!

Instead of wrapping your component in a provider, simply create provider hook. Here is an example from my project

EnvironmentContext.tsx

export function useEnvironmentProvider() {
    const environment = useStore<EnvironmentContext>({
        state: "Loading",
        registrants: {}
    });

    // eslint-disable-next-line qwik/no-use-visible-task
    useVisibleTask$(() => {
        async function getRegistrants() {
        try {
            const snapshot = await getDocs(collection(db, "registrants"));
    
            for (const doc of snapshot.docs) {
            environment.registrants[doc.id] = doc.data() as Registrant;
            }
    
            environment.state = "Valid"
        } catch (e) {
            environment.state = "Invalid";
        }
        }
    
        getRegistrants();
    });

    useContextProvider(EnvironmentContext, environment)
}

Layout.tsx

export default component$(() => {
  useEnvironmentProvider()

  return (...);
})

imMadsen avatar Apr 12 '24 10:04 imMadsen