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

Reactive tracking context warning needs to be more elaborate #2375

Closed
amiyatulu opened this issue Feb 27, 2024 · 5 comments
Closed

Reactive tracking context warning needs to be more elaborate #2375

amiyatulu opened this issue Feb 27, 2024 · 5 comments
Labels

Comments

@amiyatulu
Copy link

amiyatulu commented Feb 27, 2024

Browser shows following warning for reactive tracking.

At /home/amiya/.cargo/registry/src/index.crates.io-6f17d22bba15001f/leptos-use-0.10.2/src/use_interval_fn.rs:93:43, you access a signal or memo (defined at src/components/tests/block_number.rs:15:36) outside a reactive tracking context. This might mean your app is not responding to changes in signal values in the way you expect.

Here’s how to fix it:

1. If this is inside a `view!` macro, make sure you are passing a function, not a value.
  ❌ NO  <p>{x.get() * 2}</p>
  ✅ YES <p>{move || x.get() * 2}</p>

2. If it’s in the body of a component, try wrapping this access in a closure: 
  ❌ NO  let y = x.get() * 2
  ✅ YES let y = move || x.get() * 2.

3. If you’re *trying* to access the value without tracking, use `.get_untracked()` or `.with_untracked()` instead.

But its hard to debug by this warning.

Here is my code. Code works fine as expected, but not sure where the warning comes from.

use leptos::*;
use leptos_use::use_interval_fn;
use leptos_use::utils::Pausable;


async fn load_data(count: ReadSignal<i32>, set_count: WriteSignal<i32>){

    let new_data = move || count() + 1;
   set_count(new_data());
}

#[component]
pub fn BlockNumber() -> impl IntoView {
    let (count, set_count) = create_signal(0);  // Warning line number
    let (interval, set_interval) = create_signal(500_u64);  // Warning line number

let action = create_action(|(count, set_count): &(ReadSignal<i32>, WriteSignal<i32>)| {
    let count =  count.clone();
    let set_count = set_count.clone();
    async move { load_data(count, set_count).await }
 });

    let Pausable { .. } = use_interval_fn(
        move || {
        action.dispatch((count, set_count));
        },
        interval,
    );

    view!{
        <p>{move || count()}</p>
    }

}
@gbj
Copy link
Collaborator

gbj commented Feb 28, 2024

You mark two lines // warning line number, but I think you"re only showing one of the warnings.

At least one of them is telling you that the way you"re accessing new_data here is not reactive:

async fn load_data(count: ReadSignal<i32>, set_count: WriteSignal<i32>) {
    let new_data = move || count() + 1;
    set_count(new_data());
}

This "looks" reactive (you"re doing move || count() + 1) but actions don"t re-run in response to reactive changes, which is why it"s warning you that you"re accessing a value in a reactive way outside a reactive context.

I"m not totally sure what you"re trying to achieve here, or if this is a super simplified version of something else, but it seems like it would be much easier to do something like this:

#[component]
pub fn BlockNumber() -> impl IntoView {
    let (count, set_count) = create_signal(0);
    let (interval, set_interval) = create_signal(500_u64);

    let Pausable { .. } = use_interval_fn(
        move || {
            spawn_local(async move {
                set_count(count.get_untracked() + 1);
            })
        },
        interval,
    );

    view! {
        <p>{move || count()}</p>
    }
}

@gbj gbj added the support label Feb 28, 2024
@amiyatulu
Copy link
Author

actions don"t re-run in response to reactive changes, which is why it"s warning you

Ok got it. Using get_untracked()

@mondeja
Copy link
Contributor

mondeja commented Feb 28, 2024

Could this reactive warning track the span of the caller? That would be a lot of easier to debug.

Sometimes, the source is defined at a third party library. For example, this warning:

image

How this information could be really meaninful, when is defined at a third party library?

@gbj
Copy link
Collaborator

gbj commented Feb 28, 2024

Could this reactive warning track the span of the caller? That would be a lot of easier to debug.

The spans are sometimes broken by closures, because (afaik) you can"t use #[track_caller] on a closure.

Sometimes, the source is defined at a third party library. For example, this warning:

image

How this information could be really meaninful, when is defined at a third party library?

On the other hand, the warning you post, without any context, looks pretty useful. These are all open source libraries, right? So if it"s giving you a reference for where a signal is defined in another library, you can look and see what that os.

Ultimately this is just a linting and debugging tool that goes away in release mode. It isn"t perfect but it doesn"t need to be... it"s there to surface obviously wrong scenarios, and it works very well helping beginners fix misuses of the API in their own code. It"s always good to reduce false positives when possible but I don"t see a concrete issue here that can be addressed.

@mondeja
Copy link
Contributor

mondeja commented Feb 28, 2024

Linking to rust-lang/rust#87417

@gbj gbj closed this as completed Apr 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants