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

Components using use_state cannot be rendered conditionally #4

Open
ebenpack opened this issue Nov 24, 2022 · 3 comments
Open

Components using use_state cannot be rendered conditionally #4

ebenpack opened this issue Nov 24, 2022 · 3 comments
Labels
bug Something isn't working

Comments

@ebenpack
Copy link

Components using use_state cannot be safely rendered conditionally. Doing so can lead to a panic, with the following error message: "insufficient calls".

Here is a minimal reproducible example:
https://gist.github.com/ebenpack/3b0c3a1a2b813740003f6a4161ce8ecf

This appears to be due to the "hook rules", however it's surprising that these rules must be adhered to for the scope of the entire application. I would expect the rule to be scoped to a single component.

I'm not sure if the way this rule is applied is intended or not, but if it is I think the library would be much more usable with a more locally applied rule. E.g. it would make conditional rendering much easier and safer.

@enricozb enricozb added the bug Something isn't working label Nov 24, 2022
@enricozb
Copy link
Owner

Hi, thanks for opening this. I'm actually in the process of a rewrite that will fix this. My original implementation of the hooks and rendering flow is fundamentally flawed, and does not allow for conditional rendering.

@enricozb
Copy link
Owner

Small update:

I have a branch up for the 0.7.0 version of Intuitive, which allows for conditional rendering. It's also available as a crate as version 0.7.0-alpha.0, with the new documentation here. This isn't ready for release yet as it doesn't have any key or mouse handling.

The new documentation doesn't have an equivalent "hook rules" section yet, but it's much closer (if not the same) to React's hooks, where, within a component there can be no conditional usages of hooks, but across components that is fine.

The unmount.rs example on the 0.7.0 branch shows usages of hooks with conditional renders, and some new hooks and unmount logic.

@d4h0
Copy link

d4h0 commented Apr 21, 2023

@enricozb: Defining the hooks in a non-conditional parent component, and passing them to the conditional child components is a way to work around this issue, right?

Something like this:

#[component(Root)]
pub fn render() {
    let step = use_state(|| Step::One);
    let one_state = use_state(|| 1);
    let two_state = use_state(|| 1);

    let current_step = match step.get() {
        Step::One => One::new(step, one_state).render(),
        Step::Two => Two::new(two_state).render(),
    };

    render! {
        Embed(content: current_step)
    }
}

intuitive looks pretty neat, and I'd love to give it a try.

PS: Also, out of curiosity, if you don't mind, do you have any update regarding the rewrite? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants