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
Block props update during hydration #2665
Conversation
Visit the preview URL for this PR (updated for commit cbe3b72): https://yew-rs-api--pr2665-hydration-props-z5vgarfa.web.app (expires Mon, 30 May 2022 11:06:27 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 |
Size Comparison
✅ None of the examples has changed their size significantly. |
Wouldn't |
I've rewritten my code away from using |
I think for contexts, the situation is complicated. Fixing this may require delivering context updates as scheduler runnable so initial values of all contexts will always be available to immediate parent component and hence will be visible to components during hydration. However, delivering context updates as scheduler runnable may cause a performance penalty on context updates. I would recommend to use a prepared state (see #2650) to track the expected initial value of a context and switch to actual context value in when use_effect is called. |
Can't stop it from doing that, and apart from being clear that the only updates you get to see are the ones from prop updates to the In any case, I'm not quite sure how |
Suppose you have a component like the following: #[function_component]
fn Comp() -> Html {
let num_divs = use_context::<u32>().unwrap();
let children = 0..num_divs.map(|i| html! { <div>{i}</div> });
html! { <>{ for children }<> }
} The initial value of context Before this component finishes hydration (e.g.: due to its parent suspending), When the component is trying to hydrate itself, it will look for 2 divs instead of 1 which would cause a hydration failure. If interior mutability cannot be ignored, then you need to deliver a value that do not change until after the hydration with |
I don't think it needs to cover interior mutability, that's straying from the intended use-case and the developer should watch out for unintended side-effects (and you can do that with properties as well..) |
For properties, we can simply advise that interior mutability should almost never be used unless you have a very good reason and are willing to deal with any edge cases created by it. However, for contexts, sometimes interior mutability is the only solution. If you broadcast a Redux Store via Context, it may be subscribed by hundreds of components. React 18 has a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before long, I might have the patch ready to change all of these sleeps to a principled stepping approach. Apart from that, I have one issue following the logic of caching props in pending_props
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving since I think it's an improvement to the current situation. However, please correct me if I'm wrong, this targets not only prop changes during hydration, but any prop changes during suspension before first render. Suppose no ssr or hydration and the following:
#[derive(PartialEq, Properties)]
struct ItemDetailProps { viewed_item: u32 }
#[function_component]
fn ItemDetails(props: ItemDetailProps) -> HtmlResult {
let details = use_load_item_details(props.viewed_item)?;
html! { details }
}
#[function_component]
fn ItemView() -> Html {
let viewed_item = use_state(|| INITIAL_ITEM);
html! {
// ... some way to change viewed_item, maybe a text input, button, whatever
<Suspense>
<ItemDetails {viewed_item} />
</Suspense>
}
}
As far as I can tell, if the viewed_item
changes while the initial item is still loading item details and suspended, it would wait for the initial load to un-suspend before triggering the re-render with the pending viewed_item
prop, possibly unnecessarily delaying the actual render.
Still, better than rendering with unexpected properties during hydration.
cbe3b72
This is true. I have updated the code so it no longer does so. |
Description
Fixes #2664
This pull request delays any prop updates until the end of hydration and still allows next sibling refs to be synced to child components.
Checklist