#How to wrap the root with a context provider?

33 messages · Page 1 of 1 (latest)

unique perch
#

Hey guys, I have a ContextProvider wich should wrap my whole app.
I have a route like domain.com/admin/some-route

As you can see its a admin dashboard where you can do some changes.
I read the Context Documentation and think I know how it works.
My problem now: I need to wrap the whole route admin--> and all child routes under /admin/... with these context. How I could do this?

I need to wrap my Slot inside my layout.tsx then?

lunar ingot
#

yes you can just create your context in the layout

unique perch
#

So I could create a layout-admin.jsx and then I could wrap the Slot there :)?

unique perch
# lunar ingot yes you can just create your context in the layout

Hmmm my layout-admin looks like:

import {
  component$,
  createContext,
  Slot,
  useContextProvider,
  useStore,
} from "@builder.io/qwik";

export const MyContext = createContext("AdminContext");
export const AdminContextProvider = component$(() => {
  const state = useStore({
    count: 0,
  });

  useContextProvider(MyContext, state);
  return (
    <>
      <Slot />
    </>
  );
});

export default component$(() => {
  return (
    <>
      <AdminContextProvider />
    </>
  );
});

and my [email protected]:

import {
  component$,
  createContext,
  useClientEffect$,
  useContext,
} from "@builder.io/qwik";

export const MyContext = useContextProvider("AdminContext");

export default component$(() => {
  const state = useContext(MyContext);
  return (
    <div id="App">
      <div id="LoginPage"></div>
    </div>
  );
});

and getting this error: Code(14): Invoking 'use*()' method outside of invocation context.

lunar ingot
#

yes because you need to useContextProvider("AdminContext"); inside the component not outside

#

not sure why you define it twice though

#

useContextProvider goes once in the layout, in your page you just call useContext

#

and that should be useContext("AdminContext")

unique perch
#

w8

lunar ingot
#

plus your layout is not actually using a Slot BTW

unique perch
# lunar ingot and that should be `useContext("AdminContext")`

Like this:

export default component$(() => {
  const state = useContext("AdminContext");
  return (
    <div id="App">
      <div id="LoginPage"></div>
    </div>
  );
});

still an error: The provided Context reference is not a valid context created by createContext()

unique perch
#

my provider is return it

export const AdminContextProvider = component$(() => {
  const state = useStore({
    count: 0,
  });

  useContextProvider(MyContext, state);
  return (
    <>
      <Slot />
    </>
  );
});
lunar ingot
#

You could but it should be:

export default component$(() => {
  return (
    <>
      <AdminContextProvider>
        <Slot/>
      </AdminContextProvider>
    </>
  );
});
unique perch
# lunar ingot You could but it should be: ``` export default component$(() => { return ( ...

so the Parent is return nothing like?:

import {
  component$,
  createContext,
  Slot,
  useContextProvider,
  useStore,
} from "@builder.io/qwik";

export const MyContext = createContext("AdminContext");
export const AdminContextProvider = component$(() => {
  const state = useStore({
    count: 0,
  });

  useContextProvider(MyContext, state);
  return (
    <></>
  );
});

export default component$(() => {
  return (
    <>
      <AdminContextProvider>
        </Slot>
      </AdminContextProvider>
    </>
  );
});

my [email protected]:

export default component$(() => {
  const state = useContext("AdminContext");
});

error: Code(28): The provided Context reference is not a valid context created by createContext()

lunar ingot
#

no, AdminContextProvider should be unchanged

#

and sorry, I made a typo, it should be useContext(AdminContext) where AdminContext is the result of createContext

#

you called it MyContext but that's less specific of a name to import I think

#

So to sum up:

import {
  component$,
  createContext,
  Slot,
  useContextProvider,
  useStore,
} from "@builder.io/qwik";

export const AdminContext = createContext("AdminContext");
export const AdminContextProvider = component$(() => {
  const state = useStore({
    count: 0,
  });

  useContextProvider(MyContext, state);
  return (
    <>
      <Slot />
    </>
  );
});

export default component$(() => {
  return (
    <>
      <AdminContextProvider><Slot/></AdminContextProvider>
    </>
  );
});
#

then:

import { AdminContext } from ...

export default component$(() => {
  const state = useContext(AdminContext);
  return (
    <div id="App">
      <div id="LoginPage"></div>
    </div>
  );
});
unique perch
#

Its working!

#

@lunar ingot Thanks Mate! ❤️

lunar ingot
#

nice

unique perch
#

You helped me so much times I need to donate u xD

lunar ingot
#

haha, buy me a beer

unique perch
#

save !

#

where do you come from HAHAH :D?

lunar ingot
#

In Shanghai right now

unique perch
#

Lol nice !

#

So lets meet there 😛

#

it is possible to store functions too?

#

Define a qrl method inside my adminprovider like:

import {
  $,
  component$,
  createContext,
  Slot,
  useContextProvider,
  useStore,
} from "@builder.io/qwik";

export const AdminContext = createContext("AdminContext");
export const AdminContextProvider = component$(() => {
  const admin = useStore({
    loginStatus: false,
    user: {},
    toast: [],
  });

  const addToast$ = $((message, status) => {
    admin.toast.push({ message: message, status: status });
  });

  useContextProvider(AdminContext, admin, addToast$);
  return (
    <>
      <Slot />
    </>
  );
});

And call it like:

import {
  $,
  component$,
  useClientEffect$,
  useContext,
  useStore,
} from "@builder.io/qwik";

import { AdminContext } from "~/context/AdminContext";

export default component$(() => {
  const admin = useContext(AdminContext);
  const addToast$ = useContext(AdminContext);

  return (
    <div id="App">
      <div id="LoginPage">
        <button  onClick$={() => addToast$()}>
          trigger toast
        </button>
      </div>
    </div>
  );
});

Error: addToast$ is not a function

lunar ingot
#

you can try adding the function inside the context store