-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Context-API support #161
Comments
Hello @Hunter-Gu |
Hello @yahia-berashish I'm still trying to fix the problem: it will always get the initial value at first time painting. The key is we can't get the time when a dom mounted to the document. That make me think about Web Component. I'm working on this way now. |
Can you share a CodeSandbox/Stackblitz link so I can check out the code |
Sorry for late response. The codesandbox link: https://codesandbox.io/p/sandbox/vanjs-context-provider-poc-base-on-webcomponent-c4qp5h I haven't fix it. Because VanJS will batch all updates to next render task, so user will still see the first painting with default value. |
I think the approach you are using is wrong, even if the problem of the first painting was solved, there are still issues of passing props and having to create a separate context for actions, etc. |
Can this approach support to consume context in conditional rendering? I try to consume context in conditional rendering, it can't render as expected. VanJS Context API with conditional rendering You can search Thank you for your sharing. @yahia-berashish |
That's weird, it seems when a child component is rendered conditionally it uses the state of the last provider. |
Actually, this is why I want to find a tree structure to represent the component tree. I find there is no 'real' component in VanJS internally, the VanJS component is a way to provide I will keep trying to fix it on our versions. 😄 |
That's true, but the lack of a virtual DOM like the one you described is the main benefit of VanJS, a virtual DOM bloats the package and makes it very hard for the developer using it to know what is actually happening inside of the app. |
Totally agree with you. I like VanJS because it is so tiny and it can run in browser directly with well-designed component-oriented development. The key point of Context-API is we need to know the ancestor provider of consumer. Here are two approachs I can think of:
|
How would you go about getting the scope? |
Now, I can only know DOM tree is not a good way.
I don't have a clear idea yet. I will let you know if there are any updates. |
Hi @yahia-berashish, I create a new version, sandbox , there are still issues of removing unmounted component node. The key steps:
If integrate with Web Component, we can easily support functional component lifecycles also. I think this gives us a glance about how to support context. Give it a try if you have time, would like to hear your opinion. Thank you! |
Hello @Hunter-Gu |
My view is completely the same as yours. A separated library can keep van-core tiny, and give VanJS the ability to support most modern features. Let's talk about this. Thank you for your help. |
Hello again. |
@yahia-berashish, I apologize for being busy with my personal matters recently and not responding in a timely manner. If we don't consider implementation details for now, our ideas are completely aligned:
and these are most important. So I think we can aim to implement it as soon as possible, and then improve it based on the requirements. And this implementation should be simple, straightforward, and we can easily build upon it for further improvements. |
With VanJS' design, I don't think the Context API approach is needed here. You could just create a reactive state externally and bind to it from anywhere else in the code. When it is updated, all components bound to it will update. Here's an example of what I mean:
import van from "vanjs-core"
export const theme = van.state("light")
import van from "vanjs-core"
import theme from "./store.ts"
const { div, p, button } = van.tags;
export default function Topbar() {
return div(
p("Dark mode"),
input({
type: "checkbox",
checked: theme.val === "dark",
onchange: e => (theme.val = e.target.checked ? "dark" : "light")
})
);
}
import van from "vanjs-core"
import theme from "./store.ts"
import Topbar from "./topbar.ts"
const { div, p } = van.tags;
export default function App() {
return div(
{ className: () => theme.val === "light" ? "theme-light" : "theme-dark" },
Topbar(),
// ... rest of app
);
} |
@kwameopareasiedu Hi, thank you for your example. Actually, your example is about state management, not context. Let's review the definition of the Context API.
Context is a way to do state management, but state management is not Context. Context can be very useful when we are creating complex component, and one example that comes to mind is form group. I hope this helps you understand the intention behind this issue. |
@Hunter-Gu Having reviewed the previous discussion thread, I think I have more context (pun intended) to this. With VanJS' design, I think this may be a possible approach. Let's use a sample auth context for this example
import van from "vanjs-core"
const { div } = van.tags;
const authenticated = van.state(false);
const logout = () => {
// Logout logic
authenticated.val = false
}
const login = () => {
// Login logic
authenticated.val = true
}
export const authContext = {
authenticated: authenticated.val
login: login,
logout: logout
}
export default function AuthProvider({ childBuilder }: { childBuilder: () => HTMLElement }) {
return div(
childBuilder()
);
} I understand, the issue is in hopes of adding a Context-like API to Van, but with the current design, the state variables are private to the Any file which needs the auth context can simply import this object and work with it. This is the best way I think this can be handled similarly to how React context behaves. The only drawback here is, the context object can also be used by components not under the auth-provider in this case. |
Hello @kwameopareasiedu I think it is good to make the implementation requirements clear too:
I'm currently working at @b-rad-c VanCone add-on which can help the context development too, as well as trying to add TypeScript support for it, and will appreciate any help. |
Hello. // count.store.ts
export const countStore = writable(0);
export const doubleStore = derived(countStore, (count) => count * 2);
// counter.ts
const Counter = () => {
const count = state(0);
countStore.subscribe((current) => {
count.val = current
});
const double = state(0);
doubleStore.subscribe((current) => {
double.val = current
});
return button({onclick(){
countStore.update((current) => current + 1)
}}, "Count is: ", count, " * 2 = ", double);
}; Or maybe a shortcut syntax: // count.store.ts
export const countStore = writable(0);
// counter.ts
const Counter = () => {
const count = extract(countStore);
return button({onclick(){
countStore.update((current) => current + 1)
}}, "Count is: ", count);
}; They don't have the ability to provide different values to different parts of the DOM tree, but this functionality can be replaced with derived stores, granted, this reduces some of the flexibility React's contexts can provide, but it also reduces complexity, and believe me, the Context API can turn into a mess pretty quickly. Maybe we can try this approach @Hunter-Gu |
Discussed in #152
Originally posted by yahia-berashish October 25, 2023
Hello, I tried to migrate React Context API to VanJS. The key steps:
Current drawback: it will always get the default context when component render, because the framework hasn't bind the reactive state and dom, and it's a little tricky to find the ancestor context provider.
Try it on sandbox: https://codesandbox.io/p/sandbox/vanjs-context-provider-poc-qsgdr8?file=%2Fsrc%2Fmain.ts%3A5%2C1
I want to know if there any recommendations about this.
The text was updated successfully, but these errors were encountered: