mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Allow function_component creation based on function name (#2292)
* function_component without name * fmt * fc * update docs * remove fc
This commit is contained in:
parent
398f38d5fa
commit
73b5f6b4c1
@ -8,8 +8,8 @@ pub struct FilterProps {
|
||||
pub onset_filter: Callback<FilterEnum>,
|
||||
}
|
||||
|
||||
#[function_component(Filter)]
|
||||
pub fn filter(props: &FilterProps) -> Html {
|
||||
#[function_component]
|
||||
pub fn Filter(props: &FilterProps) -> Html {
|
||||
let filter = props.filter;
|
||||
|
||||
let cls = if props.selected {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
@ -140,18 +140,22 @@ impl Parse for FunctionComponent {
|
||||
}
|
||||
|
||||
pub struct FunctionComponentName {
|
||||
component_name: Ident,
|
||||
component_name: Option<Ident>,
|
||||
}
|
||||
|
||||
impl Parse for FunctionComponentName {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
if input.is_empty() {
|
||||
return Err(input.error("expected identifier for the component"));
|
||||
return Ok(Self {
|
||||
component_name: None,
|
||||
});
|
||||
}
|
||||
|
||||
let component_name = input.parse()?;
|
||||
|
||||
Ok(Self { component_name })
|
||||
Ok(Self {
|
||||
component_name: Some(component_name),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +175,12 @@ pub fn function_component_impl(
|
||||
name: function_name,
|
||||
return_type,
|
||||
} = component;
|
||||
|
||||
let component_name = component_name.unwrap_or_else(|| function_name.clone());
|
||||
let function_name = format_ident!(
|
||||
"{}FunctionProvider",
|
||||
function_name,
|
||||
span = function_name.span()
|
||||
);
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
|
||||
if function_name == component_name {
|
||||
|
||||
@ -1,23 +1,25 @@
|
||||
error: expected identifier
|
||||
--> $DIR/bad-name-fail.rs:8:22
|
||||
--> tests/function_component_attr/bad-name-fail.rs:8:22
|
||||
|
|
||||
8 | #[function_component(let)]
|
||||
| ^^^
|
||||
|
||||
error: unexpected token
|
||||
--> $DIR/bad-name-fail.rs:17:23
|
||||
--> tests/function_component_attr/bad-name-fail.rs:17:23
|
||||
|
|
||||
17 | #[function_component(x, y, z)]
|
||||
| ^
|
||||
|
||||
error: expected identifier
|
||||
--> $DIR/bad-name-fail.rs:26:22
|
||||
--> tests/function_component_attr/bad-name-fail.rs:26:22
|
||||
|
|
||||
26 | #[function_component(124)]
|
||||
| ^^^
|
||||
|
||||
error: the component must not have the same name as the function
|
||||
--> $DIR/bad-name-fail.rs:35:22
|
||||
warning: type `component` should have an upper camel case name
|
||||
--> tests/function_component_attr/bad-name-fail.rs:35:22
|
||||
|
|
||||
35 | #[function_component(component)]
|
||||
| ^^^^^^^^^
|
||||
| ^^^^^^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Component`
|
||||
|
|
||||
= note: `#[warn(non_camel_case_types)]` on by default
|
||||
|
||||
@ -22,13 +22,13 @@ error[E0277]: the trait bound `MissingTypeBounds: yew::Properties` is not satisf
|
||||
27 | html! { <Comp<MissingTypeBounds> /> };
|
||||
| ^^^^ the trait `yew::Properties` is not implemented for `MissingTypeBounds`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `FunctionProvider` for `comp<MissingTypeBounds>`
|
||||
= note: required because of the requirements on the impl of `FunctionProvider` for `compFunctionProvider<MissingTypeBounds>`
|
||||
|
||||
error[E0599]: the function or associated item `new` exists for struct `VChild<FunctionComponent<comp<MissingTypeBounds>>>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the function or associated item `new` exists for struct `VChild<FunctionComponent<compFunctionProvider<MissingTypeBounds>>>`, but its trait bounds were not satisfied
|
||||
--> tests/function_component_attr/generic-props-fail.rs:27:14
|
||||
|
|
||||
27 | html! { <Comp<MissingTypeBounds> /> };
|
||||
| ^^^^ function or associated item cannot be called on `VChild<FunctionComponent<comp<MissingTypeBounds>>>` due to unsatisfied trait bounds
|
||||
| ^^^^ function or associated item cannot be called on `VChild<FunctionComponent<compFunctionProvider<MissingTypeBounds>>>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/functional/mod.rs
|
||||
|
|
||||
@ -36,7 +36,7 @@ error[E0599]: the function or associated item `new` exists for struct `VChild<Fu
|
||||
| ----------------------------------------------------------- doesn't satisfy `_: yew::Component`
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`FunctionComponent<comp<MissingTypeBounds>>: yew::Component`
|
||||
`FunctionComponent<compFunctionProvider<MissingTypeBounds>>: yew::Component`
|
||||
|
||||
error[E0107]: missing generics for type alias `Comp`
|
||||
--> tests/function_component_attr/generic-props-fail.rs:30:14
|
||||
|
||||
@ -5,8 +5,8 @@ struct Props {
|
||||
a: usize,
|
||||
}
|
||||
|
||||
#[function_component()]
|
||||
fn comp(props: &Props) -> Html {
|
||||
#[function_component]
|
||||
fn Comp(props: &Props) -> Html {
|
||||
html! {
|
||||
<p>
|
||||
{ props.a }
|
||||
@ -14,4 +14,8 @@ fn comp(props: &Props) -> Html {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
fn main() {
|
||||
let _ = html! {
|
||||
<Comp a={0} />
|
||||
};
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
error: unexpected end of input, expected identifier for the component
|
||||
--> $DIR/no-name-fail.rs:8:1
|
||||
|
|
||||
8 | #[function_component()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
@ -11,7 +11,26 @@ Functions with the attribute have to return `Html` and may take a single paramet
|
||||
The parameter type needs to be a reference to a `Properties` type (ex. `props: &MyProps`).
|
||||
If the function doesn't have any parameters the resulting component doesn't accept any props.
|
||||
|
||||
The attribute doesn't replace your original function with a component. You need to provide a name as an input to the attribute which will be the identifier of the component.
|
||||
Just mark the component with the attribute. The component will be named after the function.
|
||||
|
||||
```rust
|
||||
use yew::{function_component, html, Html};
|
||||
|
||||
#[function_component]
|
||||
pub fn ChatContainer() -> Html {
|
||||
html! {
|
||||
// chat container impl
|
||||
}
|
||||
}
|
||||
|
||||
html! {
|
||||
<ChatContainer />
|
||||
};
|
||||
```
|
||||
|
||||
## Specifying a custom component name
|
||||
|
||||
You need to provide a name as an input to the attribute which will be the identifier of the component.
|
||||
Assuming you have a function called `chat_container` and you add the attribute `#[function_component(ChatContainer)]` you can use the component like this:
|
||||
|
||||
```rust
|
||||
@ -42,8 +61,8 @@ pub struct RenderedAtProps {
|
||||
pub time: String,
|
||||
}
|
||||
|
||||
#[function_component(RenderedAt)]
|
||||
pub fn rendered_at(props: &RenderedAtProps) -> Html {
|
||||
#[function_component]
|
||||
pub fn RenderedAt(props: &RenderedAtProps) -> Html {
|
||||
html! {
|
||||
<p>
|
||||
<b>{ "Rendered at: " }</b>
|
||||
@ -59,8 +78,8 @@ pub fn rendered_at(props: &RenderedAtProps) -> Html {
|
||||
```rust
|
||||
use yew::{function_component, html, use_state, Callback};
|
||||
|
||||
#[function_component(App)]
|
||||
fn app() -> Html {
|
||||
#[function_component]
|
||||
fn App() -> Html {
|
||||
let counter = use_state(|| 0);
|
||||
|
||||
let onclick = {
|
||||
@ -99,8 +118,8 @@ where
|
||||
data: T,
|
||||
}
|
||||
|
||||
#[function_component(MyGenericComponent)]
|
||||
pub fn my_generic_component<T>(props: &Props<T>) -> Html
|
||||
#[function_component]
|
||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||
where
|
||||
T: PartialEq + Display,
|
||||
{
|
||||
|
||||
@ -18,8 +18,8 @@ The easiest way to create a function component is to add the [`#[function_compon
|
||||
```rust
|
||||
use yew::{function_component, html};
|
||||
|
||||
#[function_component(HelloWorld)]
|
||||
fn hello_world() -> Html {
|
||||
#[function_component]
|
||||
fn HelloWorld() -> Html {
|
||||
html! { "Hello world" }
|
||||
}
|
||||
```
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user