Skip to content

expect_context inside a closure gives context value from later sibling's scope #4105

@paul-hansen

Description

@paul-hansen

Describe the bug
I think I have discovered a bug with expect_context / use_context where it will use the value from the last instance of provide_context for a type even though that provide_context happened in a component that isn't a parent of the component it is read in. This only happens when expect_context is used inside of a closure.

This seems to have changed since 0.6 as the code I ran into this with was working as I expected until I upgraded.

Maybe this is just a new footgun due to how Leptos 0.7 handles reactivity. If so, maybe we should simply document how to avoid it here: https://docs.rs/leptos/0.8.2/leptos/context/fn.use_context.html

Leptos Dependencies

leptos = { version = "0.8.0" }
leptos_router = { version = "0.8.0" }
axum = { version = "0.8.0", optional = true }
console_error_panic_hook = { version = "0.1", optional = true }
leptos_axum = { version = "0.8.0", optional = true }
leptos_meta = { version = "0.8.0" }

To Reproduce
(you can also just cargo leptos serve my minimal repro here)

  1. Create a component that provides a context based one of it's props
    #[component]
    pub fn ContextProvider(#[prop(optional, into)] name: String, children: Children) -> impl IntoView {
        provide_context(FieldName(name.clone()));
        view! {
            {children()}
        }
    }
  2. Read that component in another component using expect_context in a move closure
    #[component]
    pub fn CurrentContextDebug() -> impl IntoView {
        let name_closure = move || expect_context::<FieldName>().0;
        let name = expect_context::<FieldName>().0;
        view! {
            <div>"expect_context: " {name} </div>
            <div>"expect_context inside a closure: " {name_closure} </div>
        }
    }
  3. Use these components twice with different props
        <ContextProvider name="One">
            <CurrentContextDebug />
        </ContextProvider>
        <ContextProvider name="Two">
            <CurrentContextDebug />
        </ContextProvider>
  4. See that the value read from expect_context in the closure uses

Screenshots
In the below screenshot, you can see that the first context is showing the value from the second context when expect_context is called in a closure.
From: https://github.com/paul-hansen/leptos-context-bug-repro
Image

Next Steps

  • I will make a PR
  • I would like to make a PR, but need help getting started
  • I want someone else to take the time to fix this (obviously this is open source, not a job, prioritize your time accordingly.)
  • This is a low priority for me and is just shared for your information

Additional context
I have made a minimal reproduction to show this here: https://github.com/paul-hansen/leptos-context-bug-repro

I initially thought this might be related #4091 but I tried using that branch and I was still seeing the same issues. My minimal reproduction also does not use outlets.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions