Skip to content
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

Child context is affecting Parent Context permanently #1986

Closed
jsprog opened this issue Nov 4, 2023 · 1 comment
Closed

Child context is affecting Parent Context permanently #1986

jsprog opened this issue Nov 4, 2023 · 1 comment
Labels
documentation Improvements or additions to documentation

Comments

@jsprog
Copy link

jsprog commented Nov 4, 2023

Describe the bug
According to https://docs.rs/leptos/latest/leptos/fn.use_context.html, a context that is provided higher in the component tree can be used lower down, but a context that is provided lower in the tree cannot be used higher up. unfortunately, something is broken!

Leptos Dependencies

leptos = { version = "0.5.2", features = ["csr", "nightly"] }
console_error_panic_hook = "0.1.7"

To Reproduce

use leptos::*;

fn main() {
    console_error_panic_hook::set_once();
    mount_to_body(|| view!{<App/>})
}

#[component]
fn App() -> impl IntoView {
    provide_context("parent_context");
    view! {
        <Child /> // this is receiving "parent_context" as expected
        <Child /> // but this is receiving "child_context" instead of "parent_context"!
    }
}

#[component]
fn Child() -> impl IntoView {
    let context = expect_context::<&'static str>(); // first, we receive context from parent (just before the override)
    provide_context("child_context"); // then we provide context under the same type
    view! {
        <div>{format!("child (context: {context})")}</div>
    }
}

Expected behavior
The second child should receive "parent_context" instead of "child_context"

Screenshots
leptos_context_issue

Additional context
None

@gbj
Copy link
Collaborator

gbj commented Nov 4, 2023

Thanks. This behavior changed in 0.5. Pre-0.5, a new component created a new Scope. 0.5 and later, this is not the case and so context simply follows the reactive graph; components do not "exist" at runtime other than as setup functions. In your example, because there is no reactivity, all the contexts are provided in the root scope.

Making these exist in separate reactive owners (by wrapping in a closure to create an effect) works as expected:

#[component]
pub fn App() -> impl IntoView {
    provide_context("parent_context");
    view! {
        {move || view! { <Child/> }}
        {move || view! { <Child/> }}
    }
}

This is somewhat awkward syntax. Luckily, a component with no props is just a zero-argument function, and so that's actually the same as doing this, which also works as expected

#[component]
pub fn App() -> impl IntoView {
    provide_context("parent_context");
    (Child, Child)
}

Thinking about it more this is probably one of the two reasons Solid uses a context provider component instead (the other being the need for unique ID symbols, which we handle with types instead)

Obviously I need to fix the docs, as they are now wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants