mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
Proc-macro hygiene by including cx in view! macro. :-( but necessary...
This commit is contained in:
parent
79f383c89e
commit
6e89ea4447
30 changed files with 166 additions and 136 deletions
|
@ -29,6 +29,7 @@ pub fn SimpleCounter(cx: Scope, initial_value: i32) -> Element {
|
|||
|
||||
// this JSX is compiled to an HTML template string for performance
|
||||
view! {
|
||||
cx,
|
||||
<div>
|
||||
<button on:click=clear>"Clear"</button>
|
||||
<button on:click=decrement>"-1"</button>
|
||||
|
@ -40,7 +41,7 @@ pub fn SimpleCounter(cx: Scope, initial_value: i32) -> Element {
|
|||
|
||||
// Easy to use with Trunk (trunkrs.dev) or with a simple wasm-bindgen setup
|
||||
pub fn main() {
|
||||
mount_to_body(|cx| view! { <SimpleCounter initial_value=3> })
|
||||
mount_to_body(|cx| view! { cx, <SimpleCounter initial_value=3> })
|
||||
}
|
||||
|
||||
```
|
||||
|
|
|
@ -11,14 +11,14 @@ use leptos::*;
|
|||
|
||||
#[component]
|
||||
fn Button(cx: Scope, text: &'static str) -> Element {
|
||||
view! {
|
||||
view! { cx,
|
||||
<button>{text}</button>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn BoringButtons(cx: Scope) -> Element {
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<Button text="These"/>
|
||||
<Button text="Do"/>
|
||||
|
@ -35,11 +35,11 @@ Leptos uses a simple `view` macro to create the user interface. It’s much like
|
|||
1. Text within elements follows the rules of normal Rust strings (i.e., quotation marks or other string syntax)
|
||||
|
||||
```rust
|
||||
view! { <p>"Hello, world!"</p> }
|
||||
view! { cx, <p>"Hello, world!"</p> }
|
||||
```
|
||||
|
||||
2. Values can be inserted between curly braces. Reactive values
|
||||
|
||||
```rust
|
||||
view! { <p id={non_reactive_variable}>{move || value()}</p> }
|
||||
view! { cx, <p id={non_reactive_variable}>{move || value()}</p> }
|
||||
```
|
||||
|
|
|
@ -3,7 +3,7 @@ use leptos::*;
|
|||
pub fn simple_counter(cx: Scope) -> web_sys::Element {
|
||||
let (value, set_value) = create_signal(cx, 0);
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<button on:click=move |_| set_value(0)>"Clear"</button>
|
||||
<button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button>
|
||||
|
|
|
@ -34,7 +34,7 @@ pub fn Counters(cx: Scope) -> web_sys::Element {
|
|||
set_counters.update(|counters| counters.clear());
|
||||
};
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<button on:click=add_counter>
|
||||
"Add Counter"
|
||||
|
@ -61,7 +61,7 @@ pub fn Counters(cx: Scope) -> web_sys::Element {
|
|||
<ul>
|
||||
<For each={counters} key={|counter| counter.0}>{
|
||||
|cx, (id, (value, set_value)): &(usize, (ReadSignal<i32>, WriteSignal<i32>))| {
|
||||
view! {
|
||||
view! { cx,
|
||||
<Counter id=*id value=*value set_value=*set_value/>
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ fn Counter(
|
|||
|
||||
let input = move |ev| set_value(event_target_value(&ev).parse::<i32>().unwrap_or_default());
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<li>
|
||||
<button on:click={move |_| set_value.update(move |value| *value -= 1)}>"-1"</button>
|
||||
<input type="text"
|
||||
|
|
|
@ -7,5 +7,5 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
|||
fn main() {
|
||||
console_log::init_with_level(log::Level::Debug);
|
||||
|
||||
mount_to_body(|cx| view! { <Counters/> })
|
||||
mount_to_body(|cx| view! { cx, <Counters/> })
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use counters::{Counters, CountersProps};
|
|||
|
||||
#[wasm_bindgen_test]
|
||||
fn inc() {
|
||||
mount_to_body(|cx| view! { <Counters/> });
|
||||
mount_to_body(|cx| view! { cx, <Counters/> });
|
||||
|
||||
let document = leptos::document();
|
||||
let div = document.query_selector("div").unwrap().unwrap();
|
||||
|
@ -82,7 +82,7 @@ fn inc() {
|
|||
// but in user-land testing, RSX comparanda are cool
|
||||
assert_eq!(
|
||||
div.outer_html(),
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<button>"Add Counter"</button>
|
||||
<button>"Add 1000 Counters"</button>
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn fetch_example(cx: Scope) -> web_sys::Element {
|
|||
let (cat_count, set_cat_count) = create_signal::<u32>(cx, 1);
|
||||
let cats = create_resource(cx, cat_count, |count| fetch_cats(count));
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<label>
|
||||
"How many cats would you like?"
|
||||
|
@ -49,12 +49,12 @@ pub fn fetch_example(cx: Scope) -> web_sys::Element {
|
|||
<Suspense fallback={"Loading (Suspense Fallback)...".to_string()}>
|
||||
{move || {
|
||||
cats.read().map(|data| match data {
|
||||
Err(_) => view! { <pre>"Error"</pre> },
|
||||
Ok(cats) => view! {
|
||||
Err(_) => view! { cx, <pre>"Error"</pre> },
|
||||
Ok(cats) => view! { cx,
|
||||
<div>{
|
||||
cats.iter()
|
||||
.map(|src| {
|
||||
view! {
|
||||
view! { cx,
|
||||
<img src={src}/>
|
||||
}
|
||||
})
|
||||
|
|
|
@ -15,12 +15,12 @@ use users::*;
|
|||
|
||||
#[component]
|
||||
pub fn App(cx: Scope) -> Vec<Branch> {
|
||||
view! {
|
||||
view! { cx,
|
||||
<Routes>
|
||||
<Route path="" element=|cx| view! { <Main/> }>
|
||||
<Route path="users/:id" element=|cx| view! { <User/> } loader=user_data.into() />
|
||||
<Route path="stories/:id" element=|cx| view! { <Story/> } loader=story_data.into() />
|
||||
<Route path="*stories" element=|cx| view! { <Stories/> } loader=stories_data.into()/>
|
||||
<Route path="" element=|cx| view! { cx, <Main/> }>
|
||||
<Route path="users/:id" element=|cx| view! { cx, <User/> } loader=user_data.into() />
|
||||
<Route path="stories/:id" element=|cx| view! { cx, <Story/> } loader=story_data.into() />
|
||||
<Route path="*stories" element=|cx| view! { cx, <Stories/> } loader=stories_data.into()/>
|
||||
</Route>
|
||||
</Routes>
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ pub fn App(cx: Scope) -> Vec<Branch> {
|
|||
|
||||
#[component]
|
||||
pub fn Main(cx: Scope) -> Element {
|
||||
view! {
|
||||
view! { cx,
|
||||
<article>
|
||||
<Nav />
|
||||
<Outlet />
|
||||
|
|
|
@ -7,7 +7,7 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
|||
pub fn main() {
|
||||
_ = console_log::init_with_level(log::Level::Debug);
|
||||
mount_to_body(|cx| {
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<Router mode=BrowserIntegration {}><App/></Router>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@ use leptos::*;
|
|||
|
||||
#[component]
|
||||
pub fn Nav(cx: Scope) -> Element {
|
||||
view! {
|
||||
view! { cx,
|
||||
<header class="header">
|
||||
<nav class="inner">
|
||||
<Link to="/".into()>
|
||||
|
|
|
@ -70,12 +70,12 @@ pub fn Stories(cx: Scope) -> Element {
|
|||
|
||||
let hide_more_link = move || stories.read().unwrap_or(Err(())).unwrap_or_default().len() < 28;
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div class="news-view">
|
||||
<div class="news-list-nav">
|
||||
// TODO fix
|
||||
/* {move || if page() > 1 {
|
||||
view! {
|
||||
view! { cx,
|
||||
//<Link
|
||||
//attr:class="page-link"
|
||||
//to={format!("/{}?page={}", story_type(), page() - 1)}
|
||||
|
@ -85,7 +85,7 @@ pub fn Stories(cx: Scope) -> Element {
|
|||
</a>//</Link>
|
||||
}
|
||||
} else {
|
||||
view! {
|
||||
view! { cx,
|
||||
<span class="page-link disabled" aria-hidden="true">
|
||||
"< prev"
|
||||
</span>
|
||||
|
@ -105,16 +105,16 @@ pub fn Stories(cx: Scope) -> Element {
|
|||
</div>
|
||||
<main class="news-list">
|
||||
<div>
|
||||
<Suspense fallback=view! { <p>"Loading..."</p> }>
|
||||
<Suspense fallback=view! { cx, <p>"Loading..."</p> }>
|
||||
{move || match stories.read() {
|
||||
None => None,
|
||||
Some(Err(_)) => Some(view! { <p>"Error loading stories."</p> }),
|
||||
Some(Err(_)) => Some(view! { cx, <p>"Error loading stories."</p> }),
|
||||
Some(Ok(stories)) => {
|
||||
Some(view! {
|
||||
Some(view! { cx,
|
||||
<ul>
|
||||
<For each={move || stories.clone()} key=|story| story.id>{
|
||||
move |cx: Scope, story: &api::Story| {
|
||||
view! {
|
||||
view! { cx,
|
||||
<Story story={story.clone()} />
|
||||
}
|
||||
}
|
||||
|
@ -132,12 +132,12 @@ pub fn Stories(cx: Scope) -> Element {
|
|||
|
||||
#[component]
|
||||
fn Story(cx: Scope, story: api::Story) -> Element {
|
||||
view! {
|
||||
view! { cx,
|
||||
<li class="news-item">
|
||||
<span class="score">{story.points}</span>
|
||||
<span class="title">
|
||||
{if !story.url.starts_with("item?id=") {
|
||||
view! {
|
||||
view! { cx,
|
||||
<span>
|
||||
<a href={story.url} target="_blank" rel="noreferrer">
|
||||
{story.title.clone()}
|
||||
|
@ -147,13 +147,13 @@ fn Story(cx: Scope, story: api::Story) -> Element {
|
|||
}
|
||||
} else {
|
||||
let title = story.title.clone();
|
||||
view! { <Link to={format!("/stories/{}", story.id)}>{title}</Link> }
|
||||
view! { cx, <Link to={format!("/stories/{}", story.id)}>{title}</Link> }
|
||||
}}
|
||||
</span>
|
||||
<br />
|
||||
<span class="meta">
|
||||
{if story.story_type != "job" {
|
||||
view! {
|
||||
view! { cx,
|
||||
<span>
|
||||
//{"by "}
|
||||
//{story.user.map(|user| view ! { <Link to={format!("/users/{}", user)}>{&user}</Link>})}
|
||||
|
@ -169,10 +169,10 @@ fn Story(cx: Scope, story: api::Story) -> Element {
|
|||
}
|
||||
} else {
|
||||
let title = story.title.clone();
|
||||
view! { <Link to={format!("/item/{}", story.id)}>{title}</Link> }
|
||||
view! { cx, <Link to={format!("/item/{}", story.id)}>{title}</Link> }
|
||||
}}
|
||||
</span>
|
||||
{(story.story_type != "link").then(|| view! {
|
||||
{(story.story_type != "link").then(|| view! { cx,
|
||||
<span>
|
||||
//{" "}
|
||||
<span class="label">{story.story_type}</span>
|
||||
|
|
|
@ -18,11 +18,11 @@ pub fn story_data(
|
|||
pub fn Story(cx: Scope) -> Element {
|
||||
let story = use_loader::<Resource<String, Result<api::Story, ()>>>(cx);
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
{move || story.read().map(|story| match story {
|
||||
Err(_) => view! { <div class="item-view">"Error loading this story."</div> },
|
||||
Ok(story) => view! {
|
||||
Err(_) => view! { cx, <div class="item-view">"Error loading this story."</div> },
|
||||
Ok(story) => view! { cx,
|
||||
<div class="item-view">
|
||||
<div class="item-view-header">
|
||||
<a href={story.url} target="_blank">
|
||||
|
@ -31,7 +31,7 @@ pub fn Story(cx: Scope) -> Element {
|
|||
<span class="host">
|
||||
"("{story.domain}")"
|
||||
</span>
|
||||
{story.user.map(|user| view! { <p class="meta">
|
||||
{story.user.map(|user| view! { cx, <p class="meta">
|
||||
// TODO issue here in renderer
|
||||
{story.points}
|
||||
" points | by "
|
||||
|
@ -49,7 +49,7 @@ pub fn Story(cx: Scope) -> Element {
|
|||
</p>
|
||||
<ul class="comment-children">
|
||||
<For each={move || story.comments.clone().unwrap_or_default()} key={|comment| comment.id}>
|
||||
{move |cx, comment: &api::Comment| view! { <Comment comment={comment.clone()} /> }}
|
||||
{move |cx, comment: &api::Comment| view! { cx, <Comment comment={comment.clone()} /> }}
|
||||
</For>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -63,7 +63,7 @@ pub fn Story(cx: Scope) -> Element {
|
|||
pub fn Comment(cx: Scope, comment: api::Comment) -> Element {
|
||||
let (open, set_open) = create_signal(cx, true);
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<li class="comment">
|
||||
<div class="by">
|
||||
<Link to={format!("/users/{}", comment.user)}>{&comment.user}</Link>
|
||||
|
@ -71,7 +71,7 @@ pub fn Comment(cx: Scope, comment: api::Comment) -> Element {
|
|||
</div>
|
||||
<div class="text" inner_html={comment.content}></div>
|
||||
{(!comment.comments.is_empty()).then(|| {
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<div class="toggle" class:open=open>
|
||||
<a on:click=move |_| set_open(|n| *n = !*n)>
|
||||
|
@ -87,10 +87,10 @@ pub fn Comment(cx: Scope, comment: api::Comment) -> Element {
|
|||
</div>
|
||||
{move || open().then({
|
||||
let comments = comment.comments.clone();
|
||||
move || view! {
|
||||
move || view! { cx,
|
||||
<ul class="comment-children">
|
||||
<For each={move || comments.clone()} key=|comment| comment.id>
|
||||
{|cx, comment: &api::Comment| view! {
|
||||
{|cx, comment: &api::Comment| view! { cx,
|
||||
<Comment comment={comment.clone()} />
|
||||
}}
|
||||
</For>
|
||||
|
|
|
@ -17,11 +17,11 @@ pub fn user_data(
|
|||
#[component]
|
||||
pub fn User(cx: Scope) -> Element {
|
||||
let user = use_loader::<Resource<String, Result<api::User, ()>>>(cx);
|
||||
view! {
|
||||
view! { cx,
|
||||
<div class="user-view">
|
||||
{move || user.read().map(|user| match user {
|
||||
Err(_) => view! { <h1>"User not found."</h1> },
|
||||
Ok(user) => view! {
|
||||
Err(_) => view! { cx, <h1>"User not found."</h1> },
|
||||
Ok(user) => view! { cx,
|
||||
<div>
|
||||
<h1>"User: " {user.id}</h1>
|
||||
<ul class="meta">
|
||||
|
@ -31,7 +31,7 @@ pub fn User(cx: Scope) -> Element {
|
|||
<li>
|
||||
<span class="label">"Karma: "</span> {user.karma}
|
||||
</li>
|
||||
//{user.about.map(|about| view! { <li inner_html={user.about} class="about"></li> })}
|
||||
//{user.about.map(|about| view! { cx, <li inner_html={user.about} class="about"></li> })}
|
||||
</ul>
|
||||
/* <p class="links">
|
||||
<a href={format!("https://news.ycombinator.com/submitted?id={}", user.id)}>"submissions"</a>
|
||||
|
|
|
@ -12,7 +12,7 @@ pub fn main() {
|
|||
let integration = BrowserIntegration {};
|
||||
|
||||
leptos::hydrate(body().unwrap(), move |cx| {
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<Router mode=integration>
|
||||
<App />
|
||||
|
|
|
@ -70,7 +70,7 @@ async fn render_app(req: HttpRequest) -> impl Responder {
|
|||
move |cx| {
|
||||
// the actual app body/template code
|
||||
// this does NOT contain any of the data being loaded asynchronously in resources
|
||||
let shell = view! {
|
||||
let shell = view! { cx,
|
||||
<div>
|
||||
<Router mode=integration>
|
||||
<App />
|
||||
|
|
|
@ -23,7 +23,7 @@ async fn contact_data(_cx: Scope, params: ParamsMap, _url: Url) -> Option<Contac
|
|||
}
|
||||
|
||||
pub fn router_example(cx: Scope) -> Element {
|
||||
view! {
|
||||
view! { cx,
|
||||
<div id="root">
|
||||
<Router>
|
||||
<nav>
|
||||
|
@ -35,30 +35,30 @@ pub fn router_example(cx: Scope) -> Element {
|
|||
<Routes>
|
||||
<Route
|
||||
path=""
|
||||
element=move |cx| view! { <ContactList/> }
|
||||
element=move |cx| view! { cx, <ContactList/> }
|
||||
loader=contact_list_data.into()
|
||||
>
|
||||
<Route
|
||||
path=":id"
|
||||
loader=contact_data.into()
|
||||
element=move |cx| view! { <Contact/> }
|
||||
element=move |cx| view! { cx, <Contact/> }
|
||||
/>
|
||||
<Route
|
||||
path="about"
|
||||
element=move |_| view! { <p class="contact">"Here is your list of contacts"</p> }
|
||||
element=move |_| view! { cx, <p class="contact">"Here is your list of contacts"</p> }
|
||||
/>
|
||||
<Route
|
||||
path=""
|
||||
element=move |_| view! { <p class="contact">"Select a contact."</p> }
|
||||
element=move |_| view! { cx, <p class="contact">"Select a contact."</p> }
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path="about"
|
||||
element=move |cx| view! { <About/> }
|
||||
element=move |cx| view! { cx, <About/> }
|
||||
/>
|
||||
<Route
|
||||
path="settings"
|
||||
element=move |cx| view! { <Settings/> }
|
||||
element=move |cx| view! { cx, <Settings/> }
|
||||
/>
|
||||
</Routes>
|
||||
</main>
|
||||
|
@ -72,18 +72,18 @@ pub fn ContactList(cx: Scope) -> Element {
|
|||
let contacts = use_loader::<Vec<ContactSummary>>(cx);
|
||||
log::debug!("rendering <ContactList/>");
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div class="contact-list">
|
||||
<h1>"Contacts"</h1>
|
||||
<ul>
|
||||
<Suspense fallback=move || view! { <p>"Loading contacts..."</p> }>{
|
||||
<Suspense fallback=move || view! { cx, <p>"Loading contacts..."</p> }>{
|
||||
move || {
|
||||
contacts.read().map(|contacts| view! {
|
||||
contacts.read().map(|contacts| view! { cx,
|
||||
<For each=move || contacts.clone() key=|contact| contact.id>
|
||||
{move |cx, contact: &ContactSummary| {
|
||||
let id = contact.id;
|
||||
let name = format!("{} {}", contact.first_name, contact.last_name);
|
||||
view! {
|
||||
view! { cx,
|
||||
<li><A href=id.to_string()><span>{name.clone()}</span></A></li>
|
||||
}
|
||||
}}
|
||||
|
@ -101,10 +101,10 @@ pub fn ContactList(cx: Scope) -> Element {
|
|||
pub fn Contact(cx: Scope) -> Element {
|
||||
let contact = use_loader::<Option<Contact>>(cx);
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div class="contact">
|
||||
<Suspense fallback=move || view! { <p>"Loading..."</p> }>{
|
||||
move || contact.read().map(|contact| contact.map(|contact| view! {
|
||||
<Suspense fallback=move || view! { cx, <p>"Loading..."</p> }>{
|
||||
move || contact.read().map(|contact| contact.map(|contact| view! { cx,
|
||||
<section class="card">
|
||||
<h1>{contact.first_name} " " {contact.last_name}</h1>
|
||||
<p>{contact.address_1}<br/>{contact.address_2}</p>
|
||||
|
@ -117,7 +117,7 @@ pub fn Contact(cx: Scope) -> Element {
|
|||
|
||||
#[component]
|
||||
pub fn About(_cx: Scope) -> Vec<Element> {
|
||||
view! {
|
||||
view! { cx,
|
||||
<>
|
||||
<h1>"About"</h1>
|
||||
<p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
|
||||
|
@ -127,7 +127,7 @@ pub fn About(_cx: Scope) -> Vec<Element> {
|
|||
|
||||
#[component]
|
||||
pub fn Settings(_cx: Scope) -> Vec<Element> {
|
||||
view! {
|
||||
view! { cx,
|
||||
<>
|
||||
<h1>"Settings"</h1>
|
||||
<form>
|
||||
|
|
|
@ -19,6 +19,6 @@ pub fn main() {
|
|||
Todo::new(cx, 2, "Profit!".to_string()),
|
||||
]);
|
||||
|
||||
view! { <TodoMVC todos=todos/> }
|
||||
view! { cx, <TodoMVC todos=todos/> }
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ async fn render_todomvc() -> impl Responder {
|
|||
Todo::new(cx, 2, "Profit!".to_string()),
|
||||
]);
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<TodoMVC todos=todos/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ pub fn TodoMVC(cx: Scope, todos: Todos) -> Element {
|
|||
}
|
||||
});
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<main>
|
||||
<section class="todoapp">
|
||||
<header class="header">
|
||||
|
@ -193,7 +193,7 @@ pub fn TodoMVC(cx: Scope, todos: Todos) -> Element {
|
|||
<label for="toggle-all">"Mark all as complete"</label>
|
||||
<ul class="todo-list">
|
||||
<For each={filtered_todos} key={|todo| todo.id}>
|
||||
{move |cx, todo: &Todo| view! { <Todo todo={todo.clone()} /> }}
|
||||
{move |cx, todo: &Todo| view! { cx, <Todo todo={todo.clone()} /> }}
|
||||
</For>
|
||||
</ul>
|
||||
</section>
|
||||
|
@ -246,7 +246,7 @@ pub fn Todo(cx: Scope, todo: Todo) -> Element {
|
|||
set_editing(false);
|
||||
};
|
||||
|
||||
let tpl = view! {
|
||||
let tpl = view! { cx,
|
||||
<li
|
||||
class="todo"
|
||||
class:editing={editing}
|
||||
|
@ -268,7 +268,7 @@ pub fn Todo(cx: Scope, todo: Todo) -> Element {
|
|||
</label>
|
||||
<button class="destroy" on:click={move |_| set_todos.update(|t| t.remove(todo.id))}/>
|
||||
</div>
|
||||
{move || editing().then(|| view! {
|
||||
{move || editing().then(|| view! { cx,
|
||||
<input
|
||||
class="edit"
|
||||
class:hidden={move || !(editing)()}
|
||||
|
|
|
@ -6,5 +6,5 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
|||
|
||||
fn main() {
|
||||
_ = console_log::init_with_level(log::Level::Debug);
|
||||
mount_to_body(|cx| view! { <TodoMVC todos=Todos::new(cx)/> })
|
||||
mount_to_body(|cx| view! { cx, <TodoMVC todos=Todos::new(cx)/> })
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ pub fn transition_tabs(cx: Scope) -> web_sys::Element {
|
|||
}
|
||||
});
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div>
|
||||
<progress class:visible={move || transition.pending()} value={move || progress().to_string()} max="40"></progress>
|
||||
<nav class="tabs" class:pending={move || transition.pending()}>
|
||||
|
@ -70,8 +70,8 @@ pub fn transition_tabs(cx: Scope) -> web_sys::Element {
|
|||
</nav>
|
||||
<p>{move || tab.get().to_string()}</p>
|
||||
<div class="tab">
|
||||
//<Suspense fallback=view! { <div class="loader">"Loading..."</div> }>
|
||||
{move || view! { <Child page=tab /> }}
|
||||
//<Suspense fallback=view! { cx, <div class="loader">"Loading..."</div> }>
|
||||
{move || view! { cx, <Child page=tab /> }}
|
||||
//</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,11 +82,11 @@ pub fn transition_tabs(cx: Scope) -> web_sys::Element {
|
|||
pub fn Child(cx: Scope, page: ReadSignal<Tab>) -> Element {
|
||||
let data = create_resource(cx, page, |page| fake_data_load(page));
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<div class="tab-content">
|
||||
<p>
|
||||
//<Suspense fallback=view! { <div class="loader">"Lower suspense..."</div> }>
|
||||
{move || data.read().map(|data| view! {
|
||||
//<Suspense fallback=view! { cx, <div class="loader">"Lower suspense..."</div> }>
|
||||
{move || data.read().map(|data| view! { cx,
|
||||
<div>
|
||||
<p>{data}</p>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@ where
|
|||
/// Iterates over children and displays them, keyed by `PartialEq`. If you want to provide your
|
||||
/// own key function, use [Index] instead.
|
||||
///
|
||||
/// This is much more efficient than naively iterating over nodes with `.iter().map(|n| view! { ... })...`,
|
||||
/// This is much more efficient than naively iterating over nodes with `.iter().map(|n| view! { cx, ... })...`,
|
||||
/// as it avoids re-creating DOM nodes that are not being changed.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn For<E, T, G, I, K>(cx: Scope, props: ForProps<E, T, G, I, K>) -> Memo<Vec<Element>>
|
||||
|
|
|
@ -102,7 +102,7 @@ where
|
|||
});
|
||||
|
||||
// return the fallback for now, wrapped in fragment identifer
|
||||
Child::Node(view! { <div data-fragment-id={key}>{fallback.into_child(cx)}</div> })
|
||||
Child::Node(view! { cx, <div data-fragment-id={key}>{fallback.into_child(cx)}</div> })
|
||||
}
|
||||
};
|
||||
move || initial.clone()
|
||||
|
|
|
@ -19,9 +19,9 @@ syn-rsx = "0.8.1"
|
|||
uuid = { version = "1", features = ["v4"] }
|
||||
|
||||
[dev-dependencies]
|
||||
leptos_core = { path = "../leptos_core", features = ["ssr"], version = "0.0.1" }
|
||||
leptos_dom = { path = "../leptos_dom", features = ["ssr"], version = "0.0.3" }
|
||||
leptos_reactive = { path = "../leptos_reactive", features = ["ssr"], version = "0.0.3" }
|
||||
leptos_core = { path = "../leptos_core", features = ["ssr"] }
|
||||
leptos_dom = { path = "../leptos_dom", features = ["ssr"] }
|
||||
leptos_reactive = { path = "../leptos_reactive", features = ["ssr"] }
|
||||
|
||||
[features]
|
||||
csr = []
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proc_macro::TokenStream;
|
||||
use proc_macro::{TokenStream, TokenTree};
|
||||
use quote::ToTokens;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
use syn_rsx::{parse, Node, NodeType};
|
||||
|
@ -32,11 +32,24 @@ mod props;
|
|||
|
||||
#[proc_macro]
|
||||
pub fn view(tokens: TokenStream) -> TokenStream {
|
||||
match parse(tokens) {
|
||||
Ok(nodes) => render_view(&nodes, Mode::default()),
|
||||
Err(error) => error.to_compile_error(),
|
||||
let mut tokens = tokens.into_iter();
|
||||
let (cx, comma) = (tokens.next(), tokens.next());
|
||||
match (cx, comma) {
|
||||
(Some(TokenTree::Ident(cx)), Some(TokenTree::Punct(punct))) if punct.as_char() == ',' => {
|
||||
match parse(tokens.collect()) {
|
||||
Ok(nodes) => render_view(
|
||||
&proc_macro2::Ident::new(&cx.to_string(), cx.span().into()),
|
||||
&nodes,
|
||||
Mode::default(),
|
||||
),
|
||||
Err(error) => error.to_compile_error(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
_ => {
|
||||
panic!("view! macro needs a context and RSX: e.g., view! {{ cx, <div>...</div> }}")
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
|
|
|
@ -6,18 +6,18 @@ use uuid::Uuid;
|
|||
|
||||
use crate::{is_component_node, Mode};
|
||||
|
||||
pub(crate) fn render_view(nodes: &[Node], mode: Mode) -> TokenStream {
|
||||
pub(crate) fn render_view(cx: &Ident, nodes: &[Node], mode: Mode) -> TokenStream {
|
||||
let template_uid = Ident::new(
|
||||
&format!("TEMPLATE_{}", Uuid::new_v4().simple()),
|
||||
Span::call_site(),
|
||||
);
|
||||
|
||||
if nodes.len() == 1 {
|
||||
first_node_to_tokens(&template_uid, &nodes[0], mode)
|
||||
first_node_to_tokens(cx, &template_uid, &nodes[0], mode)
|
||||
} else {
|
||||
let nodes = nodes
|
||||
.iter()
|
||||
.map(|node| first_node_to_tokens(&template_uid, node, mode));
|
||||
.map(|node| first_node_to_tokens(cx, &template_uid, node, mode));
|
||||
quote! {
|
||||
{
|
||||
vec![
|
||||
|
@ -28,14 +28,14 @@ pub(crate) fn render_view(nodes: &[Node], mode: Mode) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
fn first_node_to_tokens(template_uid: &Ident, node: &Node, mode: Mode) -> TokenStream {
|
||||
fn first_node_to_tokens(cx: &Ident, template_uid: &Ident, node: &Node, mode: Mode) -> TokenStream {
|
||||
match node.node_type {
|
||||
NodeType::Doctype | NodeType::Comment => quote! {},
|
||||
NodeType::Fragment => {
|
||||
let nodes = node
|
||||
.children
|
||||
.iter()
|
||||
.map(|node| first_node_to_tokens(template_uid, node, mode));
|
||||
.map(|node| first_node_to_tokens(cx, template_uid, node, mode));
|
||||
quote! {
|
||||
{
|
||||
vec![
|
||||
|
@ -44,7 +44,7 @@ fn first_node_to_tokens(template_uid: &Ident, node: &Node, mode: Mode) -> TokenS
|
|||
}
|
||||
}
|
||||
}
|
||||
NodeType::Element => root_element_to_tokens(template_uid, node, mode),
|
||||
NodeType::Element => root_element_to_tokens(cx, template_uid, node, mode),
|
||||
NodeType::Block => node
|
||||
.value
|
||||
.as_ref()
|
||||
|
@ -60,15 +60,21 @@ fn first_node_to_tokens(template_uid: &Ident, node: &Node, mode: Mode) -> TokenS
|
|||
}
|
||||
}
|
||||
|
||||
fn root_element_to_tokens(template_uid: &Ident, node: &Node, mode: Mode) -> TokenStream {
|
||||
fn root_element_to_tokens(
|
||||
cx: &Ident,
|
||||
template_uid: &Ident,
|
||||
node: &Node,
|
||||
mode: Mode,
|
||||
) -> TokenStream {
|
||||
let mut template = String::new();
|
||||
let mut navigations = Vec::new();
|
||||
let mut expressions = Vec::new();
|
||||
|
||||
if is_component_node(node) {
|
||||
create_component(node, mode)
|
||||
create_component(cx, node, mode)
|
||||
} else {
|
||||
element_to_tokens(
|
||||
cx,
|
||||
node,
|
||||
&Ident::new("root", Span::call_site()),
|
||||
None,
|
||||
|
@ -104,7 +110,7 @@ fn root_element_to_tokens(template_uid: &Ident, node: &Node, mode: Mode) -> Toke
|
|||
Mode::Hydrate => {
|
||||
let name = node.name_as_string().unwrap();
|
||||
quote! {
|
||||
let root = #template_uid.with(|template| cx.get_next_element(template));
|
||||
let root = #template_uid.with(|template| #cx.get_next_element(template));
|
||||
// //log::debug!("root = {}", root.node_name());
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +158,7 @@ enum PrevSibChange {
|
|||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn element_to_tokens(
|
||||
cx: &Ident,
|
||||
node: &Node,
|
||||
parent: &Ident,
|
||||
prev_sib: Option<Ident>,
|
||||
|
@ -187,7 +194,7 @@ fn element_to_tokens(
|
|||
if mode == Mode::Ssr && is_root_el {
|
||||
expressions.push(quote::quote_spanned! {
|
||||
span => leptos_buffer.push_str(" data-hk=\"");
|
||||
leptos_buffer.push_str(&cx.next_hydration_key().to_string());
|
||||
leptos_buffer.push_str(&#cx.next_hydration_key().to_string());
|
||||
leptos_buffer.push('"');
|
||||
});
|
||||
}
|
||||
|
@ -195,6 +202,7 @@ fn element_to_tokens(
|
|||
// attributes
|
||||
for attr in &node.attributes {
|
||||
attr_to_tokens(
|
||||
cx,
|
||||
attr,
|
||||
&this_el_ident,
|
||||
template,
|
||||
|
@ -274,6 +282,7 @@ fn element_to_tokens(
|
|||
let next_sib = next_sibling_node(&node.children, idx + 1, next_el_id);
|
||||
|
||||
let curr_id = child_to_tokens(
|
||||
cx,
|
||||
child,
|
||||
&this_el_ident,
|
||||
if idx == 0 { None } else { prev_sib.clone() },
|
||||
|
@ -324,6 +333,7 @@ fn next_sibling_node(children: &[Node], idx: usize, next_el_id: &mut usize) -> O
|
|||
}
|
||||
|
||||
fn attr_to_tokens(
|
||||
cx: &Ident,
|
||||
node: &Node,
|
||||
el_id: &Ident,
|
||||
template: &mut String,
|
||||
|
@ -414,7 +424,7 @@ fn attr_to_tokens(
|
|||
let name = name.replacen("prop:", "", 1);
|
||||
let value = node.value.as_ref().expect("prop: blocks need values");
|
||||
expressions.push(quote_spanned! {
|
||||
span => leptos_dom::property(cx, #el_id.unchecked_ref(), #name, #value.into_property(cx))
|
||||
span => leptos_dom::property(#cx, #el_id.unchecked_ref(), #name, #value.into_property(#cx))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -426,7 +436,7 @@ fn attr_to_tokens(
|
|||
let name = name.replacen("class:", "", 1);
|
||||
let value = node.value.as_ref().expect("class: attributes need values");
|
||||
expressions.push(quote_spanned! {
|
||||
span => leptos_dom::class(cx, #el_id.unchecked_ref(), #name, #value.into_class(cx))
|
||||
span => leptos_dom::class(#cx, #el_id.unchecked_ref(), #name, #value.into_class(#cx))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -469,14 +479,14 @@ fn attr_to_tokens(
|
|||
(AttributeValue::Dynamic(value), Mode::Ssr) => {
|
||||
expressions.push(quote_spanned! {
|
||||
span => leptos_buffer.push(' ');
|
||||
leptos_buffer.push_str(&{#value}.into_attribute(cx).as_value_string(#name));
|
||||
leptos_buffer.push_str(&{#value}.into_attribute(#cx).as_value_string(#name));
|
||||
});
|
||||
}
|
||||
(AttributeValue::Dynamic(value), _) => {
|
||||
// For client-side rendering, dynamic attributes don't need to be rendered in the template
|
||||
// They'll immediately be set synchronously before the cloned template is mounted
|
||||
expressions.push(quote_spanned! {
|
||||
span => leptos_dom::attribute(cx, #el_id.unchecked_ref(), #name, {#value}.into_attribute(cx))
|
||||
span => leptos_dom::attribute(#cx, #el_id.unchecked_ref(), #name, {#value}.into_attribute(#cx))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +501,7 @@ enum AttributeValue<'a> {
|
|||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn child_to_tokens(
|
||||
cx: &Ident,
|
||||
node: &Node,
|
||||
parent: &Ident,
|
||||
prev_sib: Option<Ident>,
|
||||
|
@ -507,6 +518,7 @@ fn child_to_tokens(
|
|||
NodeType::Element => {
|
||||
if is_component_node(node) {
|
||||
component_to_tokens(
|
||||
cx,
|
||||
node,
|
||||
Some(parent),
|
||||
prev_sib,
|
||||
|
@ -521,6 +533,7 @@ fn child_to_tokens(
|
|||
)
|
||||
} else {
|
||||
PrevSibChange::Sib(element_to_tokens(
|
||||
cx,
|
||||
node,
|
||||
parent,
|
||||
prev_sib,
|
||||
|
@ -603,14 +616,14 @@ fn child_to_tokens(
|
|||
navigations.push(location);
|
||||
|
||||
let current = match current {
|
||||
Some(i) => quote! { Some(#i.into_child(cx)) },
|
||||
Some(i) => quote! { Some(#i.into_child(#cx)) },
|
||||
None => quote! { None },
|
||||
};
|
||||
expressions.push(quote! {
|
||||
leptos::insert(
|
||||
cx,
|
||||
#cx,
|
||||
#parent.clone(),
|
||||
#value.into_child(cx),
|
||||
#value.into_child(#cx),
|
||||
#before,
|
||||
#current,
|
||||
);
|
||||
|
@ -628,15 +641,15 @@ fn child_to_tokens(
|
|||
template.push_str("<!#><!/>");
|
||||
navigations.push(quote! {
|
||||
#location;
|
||||
let (#el, #co) = cx.get_next_marker(&#name);
|
||||
let (#el, #co) = #cx.get_next_marker(&#name);
|
||||
//log::debug!("get_next_marker => {}", #el.node_name());
|
||||
});
|
||||
|
||||
expressions.push(quote! {
|
||||
leptos::insert(
|
||||
cx,
|
||||
#cx,
|
||||
#parent.clone(),
|
||||
#value.into_child(cx),
|
||||
#value.into_child(#cx),
|
||||
#before,
|
||||
Some(Child::Nodes(#co)),
|
||||
);
|
||||
|
@ -647,7 +660,7 @@ fn child_to_tokens(
|
|||
// in SSR, it needs to insert the value, wrapped in comments
|
||||
Mode::Ssr => expressions.push(quote::quote_spanned! {
|
||||
span => leptos_buffer.push_str("<!--#-->");
|
||||
leptos_buffer.push_str(&#value.into_child(cx).as_child_string());
|
||||
leptos_buffer.push_str(&#value.into_child(#cx).as_child_string());
|
||||
leptos_buffer.push_str("<!--/-->");
|
||||
}),
|
||||
}
|
||||
|
@ -661,6 +674,7 @@ fn child_to_tokens(
|
|||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn component_to_tokens(
|
||||
cx: &Ident,
|
||||
node: &Node,
|
||||
parent: Option<&Ident>,
|
||||
prev_sib: Option<Ident>,
|
||||
|
@ -673,7 +687,7 @@ fn component_to_tokens(
|
|||
multi: bool,
|
||||
mode: Mode,
|
||||
) -> PrevSibChange {
|
||||
let create_component = create_component(node, mode);
|
||||
let create_component = create_component(cx, node, mode);
|
||||
let span = node.name_span().unwrap();
|
||||
|
||||
let mut current = None;
|
||||
|
@ -694,7 +708,7 @@ fn component_to_tokens(
|
|||
expressions.push(quote::quote_spanned! {
|
||||
span => // TODO wrap components but use get_next_element() instead of first_child/next_sibling?
|
||||
leptos_buffer.push_str("<!--#-->");
|
||||
leptos_buffer.push_str(&#create_component.into_child(cx).as_child_string());
|
||||
leptos_buffer.push_str(&#create_component.into_child(#cx).as_child_string());
|
||||
leptos_buffer.push_str("<!--/-->");
|
||||
|
||||
});
|
||||
|
@ -724,14 +738,14 @@ fn component_to_tokens(
|
|||
|
||||
template.push_str("<!#><!/>");
|
||||
navigations.push(quote! {
|
||||
let (#el, #co) = cx.get_next_marker(&#starts_at);
|
||||
let (#el, #co) = #cx.get_next_marker(&#starts_at);
|
||||
});
|
||||
|
||||
expressions.push(quote! {
|
||||
leptos::insert(
|
||||
cx,
|
||||
#cx,
|
||||
#parent.clone(),
|
||||
#create_component.into_child(cx),
|
||||
#create_component.into_child(#cx),
|
||||
Marker::BeforeChild(#el),
|
||||
Some(Child::Nodes(#co)),
|
||||
);
|
||||
|
@ -739,9 +753,9 @@ fn component_to_tokens(
|
|||
} else {
|
||||
expressions.push(quote! {
|
||||
leptos::insert(
|
||||
cx,
|
||||
#cx,
|
||||
#parent.clone(),
|
||||
#create_component.into_child(cx),
|
||||
#create_component.into_child(#cx),
|
||||
#before,
|
||||
None,
|
||||
);
|
||||
|
@ -757,7 +771,7 @@ fn component_to_tokens(
|
|||
}
|
||||
}
|
||||
|
||||
fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
||||
fn create_component(cx: &Ident, node: &Node, mode: Mode) -> TokenStream {
|
||||
let component_name = ident_from_tag_name(node.name.as_ref().unwrap());
|
||||
let span = node.name_span().unwrap();
|
||||
let component_props_name = Ident::new(&format!("{component_name}Props"), span);
|
||||
|
@ -765,7 +779,7 @@ fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
|||
let (initialize_children, children) = if node.children.is_empty() {
|
||||
(quote! {}, quote! {})
|
||||
} else if node.children.len() == 1 {
|
||||
let child = render_view(&node.children, mode);
|
||||
let child = render_view(cx, &node.children, mode);
|
||||
|
||||
if mode == Mode::Hydrate {
|
||||
(
|
||||
|
@ -779,7 +793,7 @@ fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
|||
)
|
||||
}
|
||||
} else {
|
||||
let children = render_view(&node.children, mode);
|
||||
let children = render_view(cx, &node.children, mode);
|
||||
|
||||
if mode == Mode::Hydrate {
|
||||
(
|
||||
|
@ -832,14 +846,14 @@ fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
|||
else if let Some(name) = attr_name.strip_prefix("prop:") {
|
||||
let value = attr.value.as_ref().expect("prop: attributes need values");
|
||||
Some(quote_spanned! {
|
||||
span => leptos_dom::property(cx, #component_name.unchecked_ref(), #name, #value.into_property(cx))
|
||||
span => leptos_dom::property(#cx, #component_name.unchecked_ref(), #name, #value.into_property(#cx))
|
||||
})
|
||||
}
|
||||
// Classes
|
||||
else if let Some(name) = attr_name.strip_prefix("class:") {
|
||||
let value = attr.value.as_ref().expect("class: attributes need values");
|
||||
Some(quote_spanned! {
|
||||
span => leptos_dom::class(cx, #component_name.unchecked_ref(), #name, #value.into_class(cx))
|
||||
span => leptos_dom::class(#cx, #component_name.unchecked_ref(), #name, #value.into_class(#cx))
|
||||
})
|
||||
}
|
||||
// Attributes
|
||||
|
@ -847,7 +861,7 @@ fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
|||
let value = attr.value.as_ref().expect("attr: attributes need values");
|
||||
let name = name.replace('_', "-");
|
||||
Some(quote_spanned! {
|
||||
span => leptos_dom::attribute(cx, #component_name.unchecked_ref(), #name, #value.into_attribute(cx))
|
||||
span => leptos_dom::attribute(#cx, #component_name.unchecked_ref(), #name, #value.into_attribute(#cx))
|
||||
})
|
||||
}
|
||||
else {
|
||||
|
@ -857,10 +871,10 @@ fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
|||
|
||||
if other_attrs.peek().is_none() {
|
||||
quote_spanned! {
|
||||
span => create_component(cx, move || {
|
||||
span => create_component(#cx, move || {
|
||||
#initialize_children
|
||||
#component_name(
|
||||
cx,
|
||||
#cx,
|
||||
#component_props_name::builder()
|
||||
#(#props)*
|
||||
#children
|
||||
|
@ -870,10 +884,10 @@ fn create_component(node: &Node, mode: Mode) -> TokenStream {
|
|||
}
|
||||
} else {
|
||||
quote_spanned! {
|
||||
span => create_component(cx, move || {
|
||||
span => create_component(#cx, move || {
|
||||
#initialize_children
|
||||
let #component_name = #component_name(
|
||||
cx,
|
||||
#cx,
|
||||
#component_props_name::builder()
|
||||
#(#props)*
|
||||
#children
|
||||
|
|
|
@ -7,7 +7,8 @@ fn simple_ssr_test() {
|
|||
|
||||
_ = create_scope(|cx| {
|
||||
let (value, set_value) = create_signal(cx, 0);
|
||||
let rendered = view! {
|
||||
let rendered = view! { cx,
|
||||
cx,
|
||||
<div>
|
||||
<button on:click=move |_| set_value(|value| *value -= 1)>"-1"</button>
|
||||
<span>"Value: " {move || value().to_string()} "!"</span>
|
||||
|
@ -34,7 +35,8 @@ fn ssr_test_with_components() {
|
|||
#[component]
|
||||
fn Counter(cx: Scope, initial_value: i32) -> Element {
|
||||
let (value, set_value) = create_signal(cx, 0);
|
||||
view! {
|
||||
view! { cx,
|
||||
cx,
|
||||
<div>
|
||||
<button on:click=move |_| set_value(|value| *value -= 1)>"-1"</button>
|
||||
<span>"Value: " {move || value().to_string()} "!"</span>
|
||||
|
@ -44,7 +46,8 @@ fn ssr_test_with_components() {
|
|||
}
|
||||
|
||||
_ = create_scope(|cx| {
|
||||
let rendered = view! {
|
||||
let rendered = view! { cx,
|
||||
cx,
|
||||
<div class="counters">
|
||||
<Counter initial_value=1/>
|
||||
<Counter initial_value=2/>
|
||||
|
|
|
@ -66,8 +66,7 @@ where
|
|||
use futures::FutureExt;
|
||||
|
||||
let initial_fut = fetcher(source());
|
||||
let initial_value = initial_fut.now_or_never();
|
||||
create_resource_with_initial_value(cx, source, fetcher, initial_value)
|
||||
initial_fut.now_or_never()
|
||||
};
|
||||
|
||||
create_resource_with_initial_value(cx, source, fetcher, initial_value)
|
||||
|
|
|
@ -142,7 +142,7 @@ where
|
|||
|
||||
let children = children().into_vec();
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<form
|
||||
method=method
|
||||
action=action
|
||||
|
|
|
@ -87,7 +87,7 @@ where
|
|||
}
|
||||
let child = children.remove(0);
|
||||
|
||||
view! {
|
||||
view! { cx,
|
||||
<a
|
||||
href=move || href().unwrap_or_default()
|
||||
prop:state={props.state.map(|s| s.to_js_value())}
|
||||
|
|
Loading…
Reference in a new issue