Skip to content

Commit

Permalink
Error on refs on components (#2863)
Browse files Browse the repository at this point in the history
* error on `ref` with components

r#ref is still allowed, so we reserve the right to reintroduce
the syntax

* fix node_refs example
  • Loading branch information
WorldSEnder committed Sep 13, 2022
1 parent 5f7dd1d commit 8eb9b5a
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 17 deletions.
2 changes: 2 additions & 0 deletions examples/node_refs/src/input.rs
Expand Up @@ -8,6 +8,7 @@ pub enum Msg {
pub struct Props {
pub on_hover: Callback<()>,
pub placeholder: AttrValue,
pub input_ref: NodeRef,
}

pub struct InputComponent;
Expand All @@ -33,6 +34,7 @@ impl Component for InputComponent {
let placeholder = ctx.props().placeholder.clone();
html! {
<input
ref={&ctx.props().input_ref}
type="text"
class="input-component"
placeholder={placeholder}
Expand Down
2 changes: 1 addition & 1 deletion examples/node_refs/src/main.rs
Expand Up @@ -89,7 +89,7 @@ impl Component for App {
<div class="input-container">
<label>{ "Password" }</label>
<InputComponent
ref={&self.refs[1]}
input_ref={&self.refs[1]}
on_hover={ctx.link().callback(|_| Msg::HoverIndex(1))}
placeholder="password"
/>
Expand Down
10 changes: 9 additions & 1 deletion packages/yew-macro/src/html_tree/html_component.rs
Expand Up @@ -257,7 +257,15 @@ impl Parse for HtmlComponentOpen {
fn parse(input: ParseStream) -> syn::Result<Self> {
TagTokens::parse_start_content(input, |input, tag| {
let ty = input.parse()?;
let props = input.parse()?;
let props: ComponentProps = input.parse()?;

if let Some(ref node_ref) = props.special().node_ref {
return Err(syn::Error::new_spanned(
&node_ref.label,
"cannot use `ref` with components. If you want to specify a property, use \
`r#ref` here instead.",
));
}

Ok(Self { tag, ty, props })
})
Expand Down
6 changes: 6 additions & 0 deletions packages/yew-macro/tests/html_macro/component-fail.stderr
Expand Up @@ -285,6 +285,12 @@ error: `int` can only be specified once but is given here again
90 | html! { <Child int=1 int=2 int=3 /> };
| ^^^

error: cannot use `ref` with components. If you want to specify a property, use `r#ref` here instead.
--> tests/html_macro/component-fail.rs:94:26
|
94 | html! { <Child int=1 ref={()} /> };
| ^^^

error: `ref` can only be specified once
--> tests/html_macro/component-fail.rs:95:35
|
Expand Down
16 changes: 1 addition & 15 deletions packages/yew/src/dom_bundle/bcomp.rs
Expand Up @@ -170,7 +170,7 @@ mod tests {
use web_sys::Element;

use super::*;
use crate::dom_bundle::{Reconcilable, ReconcileTarget};
use crate::dom_bundle::Reconcilable;
use crate::virtual_dom::{Key, VChild, VNode};
use crate::{html, scheduler, Children, Component, Context, Html, NodeRef, Properties};

Expand Down Expand Up @@ -393,20 +393,6 @@ mod tests {
};
assert_eq!(get_html(for_method, &root, &scope, &parent), expected_html);
}

#[test]
fn component_node_ref_stays_none() {
let (root, scope, parent) = setup_parent();

let node_ref = NodeRef::default();
let elem = html! { <Comp ref={node_ref.clone()}></Comp> };
let (_, elem) = elem.attach(&root, &scope, &parent, NodeRef::default());
scheduler::start_now();
assert!(node_ref.get().is_none(), "components don't have node refs");
elem.detach(&root, &parent, false);
scheduler::start_now();
assert!(node_ref.get().is_none(), "components don't have node refs");
}
}

#[cfg(target_arch = "wasm32")]
Expand Down

0 comments on commit 8eb9b5a

Please sign in to comment.