Improve grammar in website/docs (#3092)

* Improve grammar in website/docs

* Futuresolo's changes to website/docs
This commit is contained in:
Johannes Sjölund 2023-02-01 18:21:31 +01:00 committed by GitHub
parent 8d308fb617
commit 9556266061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 307 additions and 309 deletions

View File

@ -15,25 +15,25 @@ update of `yew-macro`, the generated code will be more efficient and handle any
without many (if any) modifications to the `html!` syntax.
Because the `html!` macro allows you to write code in a declarative style, your UI layout code will
closely match the HTML that is generated to the page. This becomes increasingly useful as your
application gets more interactive and your codebase gets larger. Rather than manually writing the
closely match the HTML that is generated for the page. This becomes increasingly useful as your
application gets more interactive and your codebase gets larger. Rather than manually writing
all of the code to manipulate the DOM yourself, the macro will handle it for you.
Using the `html!` macro can feel pretty magic, but it has nothing to hide. If you're curious about
how it works, try expanding the `html!` macro calls in your program. There's a useful command called
`cargo expand` which allows you to see the expansion of Rust macros. `cargo expand` isn't shipped with
`cargo` by default so you'll need to install it with `cargo install cargo-expand` if you haven't
Using the `html!` macro can feel pretty magical, but it has nothing to hide. If you are curious about
how it works, try expanding the `html!` macro calls in your program. There is a useful command called
`cargo expand` which allows you to see the expansion of Rust macros. `cargo expand` does not ship with
`cargo` by default so you will need to install it with `cargo install cargo-expand` if you have not
already. [Rust-Analyzer](https://rust-analyzer.github.io/) also provides a mechanism for
[obtaining macro output from within an IDE](https://rust-analyzer.github.io/manual.html#expand-macro-recursively).
Output from the `html!` macro is often pretty terse! This is a feature: machine-generated code can
sometimes clash with other code in an application. In order to prevent issues, `proc_macro`
sometimes clash with other code in an application. To prevent issues, `proc_macro`
"hygiene" is adhered to. Some examples include:
1. Instead of using `yew::<module>` the macro generates `::yew::<module>` to make sure that the
Yew package is referenced correctly. This is also why `::alloc::vec::Vec::new()` is called instead
of just `Vec::new()`.
2. Due to potential trait method name collisions, `<Type as Trait>` is used to make sure that we're
2. Due to potential trait method name collisions, `<Type as Trait>` is used to make sure that we are
using members from the correct trait.
## What is a virtual DOM?
@ -43,11 +43,11 @@ for your web page. A "virtual" DOM is simply a copy of the DOM that is held in a
a virtual DOM results in a higher memory overhead, but allows for batching and faster reads by avoiding
or delaying the use of browser APIs.
Having a copy of the DOM in memory can be really helpful for libraries which promote the use of
Having a copy of the DOM in memory can be helpful for libraries that promote the use of
declarative UIs. Rather than needing specific code for describing how the DOM should be modified
in response to a user event, the library can use a generalized approach with DOM "diffing". When a Yew
component is updated and wants to change how it is rendered, the Yew library will build a second copy
of the virtual DOM and directly compare to a virtual DOM which mirrors what is currently on screen.
of the virtual DOM and directly compare it to a virtual DOM which mirrors what is currently on screen.
The "diff" (or difference) between the two can be broken down into incremental updates and applied in
a batch with browser APIs. Once the updates are applied, the old virtual DOM copy is discarded and the
new copy is saved for future diff checks.

View File

@ -12,7 +12,7 @@ to update a value, you must instantiate a new value.
Properties, like in React, are propagated from ancestors to
children. This means that the properties must live when each component is
updated. This is why properties should —ideally— be cheap to clone. In order to
updated. This is why properties should —ideally— be cheap to clone. To
achieve this we usually wrap things in `Rc`.
Immutable types are a great fit for holding property's values because they can

View File

@ -9,7 +9,7 @@ description: 'Make your app faster'
**Note: if you're unsure about some of the terms used in this section, the Rust Book has a useful
[chapter about smart pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html).**
In an effort to avoid cloning large amounts of data to create props when re-rendering, we can use
To avoid cloning large amounts of data to create props when re-rendering, we can use
smart pointers to only clone a reference to the data instead of the data itself. If you pass
references to the relevant data in your props and child components instead of the actual data you
can avoid cloning any data until you need to modify it in the child component, where you can
@ -31,12 +31,12 @@ data cheaply, then it isn't worth putting it behind a smart pointer. For structu
can be data-heavy like `Vec`s, `HashMap`s, and `String`s using smart pointers is likely to bring
performance improvements.
This optimization works best if the values are never updated by the children, and even better, if
This optimization works best if the values are never updated by the children, and even better if
they are rarely updated by parents. This makes `Rc<_>s` a good choice for wrapping property values
in for pure components.
in pure components.
However, it must be noted that unless you need to clone the data yourself in the child component,
this optimization is not only useless, it also adds unnecessary cost of reference counting. Props
this optimization is not only useless, but it also adds the unnecessary cost of reference counting. Props
in Yew are already reference counted and no data clones occur internally.
## View functions
@ -62,22 +62,22 @@ identical props. Yew compares the props internally and so the UI is only re-rend
Arguably, the largest drawback to using Yew is the long time it takes to compile Yew apps. The time
taken to compile a project seems to be related to the quantity of code passed to the `html!` macro.
This tends to not be much of an issue for smaller projects, but for larger applications it makes
This tends to not be much of an issue for smaller projects, but for larger applications, it makes
sense to split code across multiple crates to minimize the amount of work the compiler has to do for
each change made to the application.
One possible approach is to make your main crate handle routing/page selection, and then make a
different crate for each page, where each page could be a different component, or just a big
function that produces `Html`. Code which is shared between the crates containing different parts of
the application could be stored in a separate crate which is depended on throughout the project.
In the best case scenario, you go from rebuilding all of your code on each compile to rebuilding
different crate for each page, where each page could be a different component or just a big
function that produces `Html`. Code that is shared between the crates containing different parts of
the application could be stored in a separate crate which the project depends on.
In the best-case scenario, you go from rebuilding all of your code on each compile to rebuilding
only the main crate, and one of your page crates. In the worst case, where you edit something in the
"common" crate, you will be right back to where you started: compiling all code that depends on that
commonly shared crate, which is probably everything else.
If your main crate is too heavyweight, or you want to rapidly iterate on a deeply nested page \(eg.
a page that renders on top of another page\), you can use an example crate to create a simplified
implementation of the main page and render the component you are working on on top of that.
implementation of the main page and additionally render the component you are working on.
## Reducing binary sizes
@ -133,7 +133,7 @@ that require occasional attention and tweaking. Use these experimental options w
### wasm-opt
Further more it is possible to optimize size of `wasm` code.
Further, it is possible to optimize the size of `wasm` code.
The Rust Wasm Book has a section about reducing the size of Wasm binaries:
[Shrinking .wasm size](https://rustwasm.github.io/book/game-of-life/code-size.html)

View File

@ -6,7 +6,7 @@ description: 'Rendering into out-of-tree DOM nodes'
## What is a portal?
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
`yew::create_portal(child, host)` returns a `Html` value that renders `child` not hierarchically under its parent component,
`yew::create_portal(child, host)` returns an `Html` value that renders `child` not hierarchically under its parent component,
but as a child of the `host` element.
## Usage

View File

@ -5,17 +5,17 @@ description: 'Render Yew on the server-side.'
# Server-side Rendering
By default, Yew components render at the client side. When a viewer
visits a website, the server sends a skeleton html file without any actual
By default, Yew components render on the client side. When a viewer
visits a website, the server sends a skeleton HTML file without any actual
content and a WebAssembly bundle to the browser.
Everything is rendered at the client side by the WebAssembly
Everything is rendered on the client side by the WebAssembly
bundle. This is known as client-side rendering.
This approach works fine for most websites, with some caveats:
1. Users will not be able to see anything until the entire WebAssembly
bundle is downloaded and initial render has completed.
This can result in poor user experience if the user is using a slow network.
bundle is downloaded and the initial render has been completed.
This can result in a poor experience for users on a slow network.
2. Some search engines do not support dynamically rendered web content and
those who do usually rank dynamic websites lower in the search results.
@ -24,9 +24,9 @@ To solve these problems, we can render our website on the server side.
## How it Works
Yew provides a `ServerRenderer` to render pages on the
server-side.
server side.
To render Yew components at the server-side, you can create a renderer
To render Yew components on the server side, you can create a renderer
with `ServerRenderer::<App>::new()` and call `renderer.render().await`
to render `<App />` into a `String`.
@ -66,20 +66,19 @@ for the first time.
:::caution Web APIs are not available!
Web APIs such as `web_sys` are not available when your component is
rendering on the server-side.
rendering on the server side.
Your application will panic if you try to use them.
You should isolate logics that need Web APIs in `use_effect` or
`use_effect_with_deps` as effects are not executed during server side
rendering.
`use_effect_with_deps` as effects are not executed during server-side rendering.
:::
:::danger Struct Components
Whilst it's possible to use Struct Components with server-side rendering,
there's no clear boundaries between client-side safe logic like the
While it is possible to use Struct Components with server-side rendering,
there are no clear boundaries between client-side safe logic like the
`use_effect` hook for function components and lifecycle events are invoked
in a different order than client side.
in a different order than the client side.
In addition, Struct Components will continue to accept messages until all of its
children are rendered and `destroy` method is called. Developers need to
@ -93,33 +92,32 @@ prefer function components unless you have a good reason not to.
## Data Fetching during Server-side Rendering
Data fetching is one of the difficult point with server side rendering
and hydration.
Data fetching is one of the difficult points with server-side rendering and hydration.
Traditionally, when a component renders, it is instantly available
(outputs a virtual dom to be rendered). This works fine when the
(outputs a virtual DOM to be rendered). This works fine when the
component does not want to fetch any data. But what happens if the component
wants to fetch some data during rendering?
In the past, there's no mechanism for Yew to detect whether a component is still
fetching data. The data fetching client is responsible to implement
a solution to detect what's being requested during initial render and triggers
In the past, there was no mechanism for Yew to detect whether a component is still
fetching data. The data-fetching client is responsible to implement
a solution to detect what is being requested during the initial render and triggers
a second render after requests are fulfilled. The server repeats this process until
no more pending requests are added during a render before returning a response.
Not only this wastes CPU resources by repeatedly rendering components,
but the data client also needs to provide a way to make the data fetched on
the server-side available during hydration process to make sure that the
virtual dom returned by initial render is consistent with the
This not only wastes CPU resources by repeatedly rendering components,
but the data client also needs to provide a way to make the data fetched on the
server side available during the hydration process to make sure that the
virtual DOM returned by the initial render is consistent with the
server-side rendered DOM tree which can be hard to implement.
Yew takes a different approach by trying to solve this issue with `<Suspense />`.
Suspense is a special component that when used on the client-side,
provides a way to show a fallback UI while the component is fetching
Suspense is a special component that when used on the client side, provides a
way to show a fallback UI while the component is fetching
data (suspended) and resumes to normal UI when the data fetching completes.
When the application is rendered on the server-side, Yew waits until a
When the application is rendered on the server side, Yew waits until a
component is no longer suspended before serializing it into the string
buffer.
@ -127,21 +125,21 @@ During the hydration process, elements within a `<Suspense />` component
remains dehydrated until all of its child components are no longer
suspended.
With this approach, developers can build a client-agnostic, SSR ready
With this approach, developers can build a client-agnostic, SSR-ready
application with data fetching with very little effort.
## SSR Hydration
Hydration is the process that connects a Yew application to the
server-side generated HTML file. By default, `ServerRender` prints
hydratable html string which includes additional information to facilitate hydration.
When the `Renderer::hydrate` method is called, instead of start rendering from
hydratable HTML string which includes additional information to facilitate hydration.
When the `Renderer::hydrate` method is called, instead of starting rendering from
scratch, Yew will reconcile the Virtual DOM generated by the application
with the html string generated by the server renderer.
with the HTML string generated by the server renderer.
:::caution
To successfully hydrate an html representation created by the
To successfully hydrate an HTML representation created by the
`ServerRenderer`, the client must produce a Virtual DOM layout that
exactly matches the one used for SSR including components that do not
contain any elements. If you have any component that is only useful in
@ -153,15 +151,15 @@ position of the extra component.
During Hydration, components schedule 2 consecutive renders after it is
created. Any effects are called after the second render completes.
It is important to make sure that the render function of the your
component is side-effect free. It should not mutate any states or trigger
It is important to make sure that the render function of your
component is free of side effects. It should not mutate any states or trigger
additional renders. If your component currently mutates states or triggers
additional renders, move them into an `use_effect` hook.
additional renders, move them into a `use_effect` hook.
It's possible to use Struct Components with server-side rendering in
It is possible to use Struct Components with server-side rendering in
hydration, the view function will be called
multiple times before the rendered function will be called.
The DOM is considered as not connected until rendered function is called,
The DOM is considered as not connected until the rendered function is called,
you should prevent any access to rendered nodes
until `rendered()` method is called.
@ -190,7 +188,7 @@ Example: [ssr_router](https://github.com/yewstack/yew/tree/master/examples/ssr_r
:::caution
Server-side rendering is currently experiemental. If you find a bug, please file
Server-side rendering is currently experimental. If you find a bug, please file
an issue on [GitHub](https://github.com/yewstack/yew/issues/new?assignees=&labels=bug&template=bug_report.md&title=).
:::

View File

@ -40,7 +40,7 @@ impl Component for Comp {
}
```
The function passed to `callback` must always take a parameter. For example, the `onclick` handler requires a function which takes a parameter of type `MouseEvent`. The handler can then decide what kind of message should be sent to the component. This message is scheduled for the next update loop unconditionally.
The function passed to `callback` must always take a parameter. For example, the `onclick` handler requires a function that takes a parameter of type `MouseEvent`. The handler can then decide what kind of message should be sent to the component. This message is scheduled for the next update loop unconditionally.
If you need a callback that might not need to cause an update, use `batch_callback`.

View File

@ -2,13 +2,13 @@
title: 'Higher Order Components'
---
There are several cases where Struct components dont directly support a feature (ex. Suspense) or require a lot of boiler plate to use the features (ex. Context).
There are several cases where Struct components do not directly support a feature (ex. Suspense) or require a lot of boilerplate code to use the features (ex. Context).
In those cases it is recommended to create function components that are higher order components.
In those cases, it is recommended to create function components that are higher-order components.
## Higher Order Components Definition
Higher Order Components are components that dont add any new Html and only wrap some other component to provide extra functionality.
Higher Order Components are components that do not add any new HTML and only wrap some other components to provide extra functionality.
### Example

View File

@ -5,22 +5,22 @@ description: 'Components in Yew'
## What are Components?
Components are the building blocks of Yew. They manage their own state and can render themselves to the DOM.
Components are the building blocks of Yew. They manage an internal state and can render elements to the DOM.
Components are created by implementing the `Component` trait for a type.
## Writing Component's markup
Yew uses Virtual DOM to render elements to the DOM. The Virtual DOM tree can be constructed by using the
`html!` macro. `html!` uses syntax which is similar to HTML but is not exactly the same. The rules are also
much stricter. It also provides super-powers like conditional rendering and rendering of lists using iterators.
`html!` macro. `html!` uses a syntax which is similar to HTML but is not the same. The rules are also
much stricter. It also provides superpowers like conditional rendering and rendering of lists using iterators.
:::info
[Learn more about the `html!` macro, how it's used and its syntax](concepts/html/introduction.mdx)
[Learn more about the `html!` macro, how it is used and its syntax](concepts/html/introduction.mdx)
:::
## Passing data to a component
Yew components use _props_ to communicate between parent and children. A parent component may pass any data as props to
Yew components use _props_ to communicate between parents and children. A parent component may pass any data as props to
its children. Props are similar to HTML attributes but any Rust type can be passed as props.
:::info

View File

@ -17,7 +17,7 @@ stages in the lifecycle of a component.
### Create
When a component is created, it receives properties from its parent component and is stored within
the `Context<Self>` that's passed down to the `create` method. The properties can be used to
the `Context<Self>` that is passed down to the `create` method. The properties can be used to
initialize the component's state and the "link" can be used to register callbacks or send messages to the component.
```rust
@ -137,7 +137,7 @@ impl Component for MyComponent {
```
:::tip note
Note that this lifecycle method does not require an implementation and will do nothing by default.
Note that this lifecycle method does not require implementation and will do nothing by default.
:::
### Update
@ -147,7 +147,7 @@ Communication with components happens primarily through messages which are handl
based on what the message was, and determine if it needs to re-render itself. Messages can be sent
by event listeners, child components, Agents, Services, or Futures.
Here's an example of what an implementation of `update` could look like:
Here is an example of what an implementation of `update` could look like:
```rust
use yew::{Component, Context, html, Html};
@ -200,8 +200,8 @@ impl Component for MyComponent {
### Changed
Components may be re-rendered by their parents. When this happens, they could receive new properties
and need to re-render. This design facilitates parent to child component communication by just
changing the values of a property. There is a default implementation which re-renders the component
and need to re-render. This design facilitates parent-to-child component communication by just
changing the values of a property. There is a default implementation that re-renders the component
when props are changed.
### Destroy
@ -212,8 +212,8 @@ before it is destroyed. This method is optional and does nothing by default.
### Infinite loops
Infinite loops are possible with Yew's lifecycle methods, but are only caused when trying to update
the same component after every render when that update also requests the component to be rendered.
Infinite loops are possible with Yew's lifecycle methods but are only caused when trying to update
the same component after every render, when that update also requests the component to be rendered.
A simple example can be seen below:
@ -259,7 +259,7 @@ Let's run through what happens here:
component needs to re-render.
7. Jump back to 2.
You can still schedule updates in the `rendered` method and it's often useful to do so, but
You can still schedule updates in the `rendered` method and it is often useful to do so, but
consider how your component will terminate this loop when you do.
## Associated Types
@ -276,7 +276,7 @@ impl Component for MyComponent {
```
The `Message` type is used to send messages to a component after an event has taken place; for
example you might want to undertake some action when a user clicks a button or scrolls down the
example, you might want to undertake some action when a user clicks a button or scrolls down the
page. Because components tend to have to respond to more than one event, the `Message` type will
normally be an enum, where each variant is an event to be handled.
@ -301,5 +301,5 @@ enum Msg {
## Lifecycle Context
All component lifecycle methods take a context object. This object provides a reference to component's scope, which
All component lifecycle methods take a context object. This object provides a reference to the component's scope, which
allows sending messages to a component and the props passed to the component.

View File

@ -5,7 +5,7 @@ description: 'Parent to child communication'
Properties enable child and parent components to communicate with each other.
Every component has an associated properties type which describes what is passed down from the parent.
In theory this can be any type that implements the `Properties` trait, but in practice there's no
In theory, this can be any type that implements the `Properties` trait, but in practice, there is no
reason for it to be anything but a struct where each field represents a property.
## Derive macro
@ -17,7 +17,7 @@ Types for which you derive `Properties` must also implement `PartialEq`.
### Field attributes
When deriving `Properties`, all fields are required by default.
The following attributes allow you to give your props initial values which will be used unless they're set to another value.
The following attributes allow you to give your props initial values which will be used unless they are set to another value.
:::tip
Attributes aren't visible in Rustdoc generated documentation.
@ -75,7 +75,7 @@ fn create_default_link_color() -> LinkColor {
pub struct LinkProps {
/// The link must have a target.
href: AttrValue,
/// Also notice that we're using AttrValue instead of String
/// Also notice that we are using AttrValue instead of String
text: AttrValue,
/// Color of the link. Defaults to `Blue`.
#[prop_or_else(create_default_link_color)]
@ -83,7 +83,7 @@ pub struct LinkProps {
/// The view function will not specify a size if this is None.
#[prop_or_default]
size: Option<u32>,
/// When the view function doesn't specify active, it defaults to true.
/// When the view function does not specify active, it defaults to true.
#[prop_or(true)]
active: bool,
}
@ -93,7 +93,7 @@ pub struct LinkProps {
The `yew::props!` macro allows you to build properties the same way the `html!` macro does it.
The macro uses the same syntax as a struct expression except that you can't use attributes or a base expression (`Foo { ..base }`).
The macro uses the same syntax as a struct expression except that you cannot use attributes or a base expression (`Foo { ..base }`).
The type path can either point to the props directly (`path::to::Props`) or the associated properties of a component (`MyComp::Properties`).
```rust

View File

@ -5,7 +5,7 @@ description: "Component's Scope"
## Component's `Scope<_>` API
The component "`Scope`" is the mechanism through which components are able to create callbacks and update themselves
The component "`Scope`" is the mechanism through which components can create callbacks and update themselves
using messages. We obtain a reference to this by calling `link()` on the context object passed to the component.
### `send_message`
@ -19,7 +19,7 @@ Sends multiple messages to the component at the same time.
This is similar to `send_message` but if any of the messages cause the `update` method to return `true`,
the component will re-render after all messages in the batch have been processed.
If the given vector is empty, this function doesn't do anything.
If the given vector is empty, this function does nothing.
### `callback`

View File

@ -36,7 +36,7 @@ The code can be found in the <desc> tag of the svgs.
- Private - Spawn a new agent in a web worker for every new bridge. This is good for moving shared but
independent behavior that communicates with the browser out of components. When
the the connected bridge is dropped, the agent will disappear.
the connected bridge is dropped, the agent will disappear.
- Global \(WIP\)
@ -61,4 +61,4 @@ with other threads, so the cost is substantially higher than just calling a func
## Further reading
- The [web_worker_fib](https://github.com/yewstack/yew/tree/master/examples/web_worker_fib) example shows how
components can send message to and receive message from agents.
components can send messages to and receive messages from agents.

View File

@ -1,14 +1,14 @@
---
title: 'CSS with classes!'
description: 'A handy macro to handle classes'
comment: 'Keep this file as short and simple as possible. Its purpose is to ease in the reader into components in Yew instead of providing proper API docs'
comment: 'Keep this file as short and simple as possible. Its purpose is to ease the reader into components in Yew instead of providing proper API docs'
---
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
Yew does not natively provide a css in rust solution, but helps with styling by providing
programmatic ways to interact with the html `class` attribute.
Yew does not natively provide a CSS-in-Rust solution but helps with styling by providing
programmatic ways to interact with the HTML `class` attribute.
## Classes
@ -88,7 +88,7 @@ We will expand upon this concept in [more CSS](../../more/css).
## Inline Styles
Currently Yew does not provide any special help with inline styles specified via the `styles` attribute,
but you can use it like any other html attribute:
but you can use it like any other HTML attribute:
```rust
use yew::{classes, html};

View File

@ -1,13 +1,13 @@
---
title: 'HTML with html!'
description: 'Its HTML but not quite!'
comment: 'Keep this file as short and simple as possible. Its purpose is to ease in the reader into components in Yew instead of providing proper API docs'
comment: 'Keep this file as short and simple as possible. Its purpose is to ease the reader into components in Yew instead of providing proper API docs'
---
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
You can write expressions resembling HTML with the `html!` macro. Behind the scenes Yew turns
You can write expressions resembling HTML with the `html!` macro. Behind the scenes, Yew turns
it into rust code representing the DOM to generate.
```rust
@ -19,7 +19,7 @@ let my_header: Html = html! {
```
Similar to format expressions, there is an easy way to embed values from the surrounding
context into the html by applying curly brackets:
context into the HTML by applying curly brackets:
```rust
use yew::prelude::*;
@ -39,9 +39,9 @@ let combined_html: Html = html! {
};
```
One rule major rule comes with use of `html!` - you can only return 1 wrapping node.
One major rule comes with the use of `html!` - you can only return 1 wrapping node.
To render a list of multiple elements, `html!` allows fragments. Fragments are tags
without a name, that produce no html element by themselves.
without a name, that produce no HTML element by themselves.
<Tabs>
<TabItem value="Invalid" label="Invalid">
@ -49,7 +49,7 @@ without a name, that produce no html element by themselves.
```rust , compile_fail
use yew::html;
// error: only one root html element allowed
// error: only one root HTML element allowed
html! {
<div></div>
@ -64,7 +64,7 @@ html! {
```rust
use yew::html;
// fixed: using html fragments
// fixed: using HTML fragments
html! {
<>
<div></div>

View File

@ -1,7 +1,7 @@
---
title: 'JS with RS'
description: 'Javascript with Rust'
comment: 'Keep this file as short and simple as possible. Its purpose is to ease in the reader into components in Yew instead of providing proper API docs'
description: 'JavaScript with Rust'
comment: 'Keep this file as short and simple as possible. Its purpose is to ease the reader into components in Yew instead of providing proper API docs'
---
import Tabs from '@theme/Tabs'
@ -12,17 +12,17 @@ import TabItem from '@theme/TabItem'
> accessible where necessary.
As of today, WebAssembly is not feature-complete for DOM interactions. This means even in Yew we
sometimes rely on calling Javascript. What follows is an overview of the involved libraries.
sometimes rely on calling JavaScript. What follows is an overview of the involved libraries.
## wasm-bindgen
[`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) is a library and tool that enables calls to javascript from rust and back to rust from javascript.
[`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) is a library and tool that bridges calls between JavaScript and Rust functions.
We highly recommend you take a look at their [documentation](https://rustwasm.github.io/docs/wasm-bindgen/) and our [quick guide](./wasm-bindgen.mdx).
## web-sys
The [`web-sys` crate](https://crates.io/crates/web-sys) provides bindings for Web APIs and allows us to write Javascript code in a rustyfied and safe way.
The [`web-sys` crate](https://crates.io/crates/web-sys) provides bindings for Web APIs and allows us to write JavaScript code in a rustyfied and safe way.
Example:

View File

@ -14,7 +14,7 @@ Yew uses `wasm-bindgen` to interact with the browser through a number of crates:
- [`wasm-bindgen-futures`](https://crates.io/crates/wasm-bindgen-futures)
- [`web-sys`](https://crates.io/crates/web-sys)
This section will explore some of these crates in a high level in order to make it easier to understand
This section will explore some of these crates at a high level, to make it easier to understand
and use `wasm-bindgen` APIs with Yew. For a more in-depth guide to `wasm-bindgen` and its associated
crates then check out [The `wasm-bindgen` Guide](https://rustwasm.github.io/docs/wasm-bindgen/).
@ -29,14 +29,14 @@ over using `wasm-bindgen`.
This crate provides many of the building blocks for the rest of the crates above. In this section we
are only going to cover two main areas of the `wasm-bindgen` crate and that is the macro and some
types / traits you will see pop up again and again.
types/traits you will see pop up again and again.
### `#[wasm_bindgen]` macro
The `#[wasm_bindgen]` macro provides an interface between Rust and JavaScript, providing a system
for translating between the two. Using this macro is more advanced, and you shouldn't need to reach
for translating between the two. Using this macro is more advanced, and you should not need to reach
for it unless you are trying to use an external JavaScript library. The `js-sys` and `web-sys`
crates expose `wasm-bindgen` definitions for built-in Javascript types and browser APIs.
crates expose `wasm-bindgen` definitions for built-in JavaScript types and browser APIs.
Let's go over a simple example of using the `#[wasm-bindgen]` macro to import some specific flavours
of the [`console.log`](https://developer.mozilla.org/en-US/docs/Web/API/Console/log) function.
@ -77,11 +77,11 @@ _This example was adapted from [1.2 Using console.log of The `wasm-bindgen` Guid
### Simulating inheritance
Inheritance between JavaScript classes is a core feature of the Javascript language, and the DOM
Inheritance between JavaScript classes is a core feature of the Javascript language and the DOM
(Document Object Model) is designed around it. When types are imported using `wasm-bindgen` you can
also add attributes that describe their inheritance.
In Rust this inheritance is represented using the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
In Rust, this inheritance is represented using the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
and [`AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) traits. An example of this
might help; so say you have three types `A`, `B`, and `C` where `C` extends `B` which in turn
extends `A`.
@ -97,17 +97,17 @@ traits in the following way:
These implementations allow you to call a method from `A` on an instance of `C` and to use `C` as if
it was `&B` or `&A`.
Its important to note that every single type imported using `#[wasm-bindgen]` has the same root type,
It is important to note that every single type imported using `#[wasm-bindgen]` has the same root type,
you can think of it as the `A` in the example above, this type is [`JsValue`](#jsvalue) which has
its own section below.
its section below.
_[extends section in The `wasm-bindgen` Guide](https://rustwasm.github.io/docs/wasm-bindgen/reference/attributes/on-js-imports/extends.html)_
### [`JsValue`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html) {#jsvalue}
This is a representation of an object owned by JavaScript, this is a root catch-all type for `wasm-bindgen`.
Any type that comes from `wasm-bindgen` is a `JsValue` and this is because JavaScript doesn't have
a strong type system so any function that accepts a variable `x` doesn't define its type so `x` can be
Any type that comes from `wasm-bindgen` is a `JsValue` and this is because JavaScript does not have
a strong type system so any function that accepts a variable `x` does not define its type so `x` can be
a valid JavaScript value; hence `JsValue`. If you are working with imported functions or types that
accept a `JsValue`, then any imported value is _technically_ valid.
@ -119,12 +119,12 @@ _[`JsValue` documentation](https://rustwasm.github.io/wasm-bindgen/api/wasm_bind
### [`JsCast`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html) {#JsCast}
Rust has a strong type system and JavaScript...doesn't 😞. In order for Rust to maintain these
strong types but still be convenient the WebAssembly group came up with a pretty neat trait `JsCast`.
Rust has a strong type system and JavaScript...doesn't 😞. For Rust to maintain these
strong types but still be convenient, the WebAssembly group came up with a pretty neat trait `JsCast`.
Its job is to help you move from one JavaScript "type" to another, which sounds vague, but it means
that if you have one type which you know is really another then you can use the functions of `JsCast`
to jump from one type to the other. It's a nice trait to get to know when working with `web-sys`,
`wasm_bindgen`, `js-sys` - you'll notice lots of types will implement `JsCast` from those crates.
that if you have one type which you know is another, then you can use the functions of `JsCast`
to jump from one type to the other. It is a nice trait to get to know when working with `web-sys`,
`wasm_bindgen`, `js-sys` - you will notice lots of types will implement `JsCast` from those crates.
`JsCast` provides both checked and unchecked methods of casting - so that at runtime if you are
unsure what type a certain object is you can try to cast it which returns possible failure types like
@ -132,9 +132,9 @@ unsure what type a certain object is you can try to cast it which returns possib
[`Result`](https://doc.rust-lang.org/std/result/enum.Result.html).
A common example of this in [`web-sys`](./web-sys.mdx) is when you are trying to get the
target of an event, you might know what the target element is but the
[`web_sys::Event`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Event.html) API will always return an [`Option<web_sys::EventTarget>`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.target)
so you will need to cast it to the element type. so you can call its methods.
target of an event. You might know what the target element is but the
[`web_sys::Event`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Event.html) API will always return an [`Option<web_sys::EventTarget>`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.target).
You will need to cast it to the element type so you can call its methods.
```rust
// need to import the trait.
@ -161,7 +161,7 @@ The [`dyn_ref`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/trait.J
method is a checked cast that returns an `Option<&T>` which means the original type
can be used again if the cast failed and thus returned `None`. The
[`dyn_into`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html#method.dyn_into)
method will consume `self`, as per convention for into methods in Rust, and the type returned is
method will consume `self`, as per convention for `into` methods in Rust, and the type returned is
`Result<T, Self>`. If the casting fails, the original `Self` value is returned in `Err`. You can try again
or do something else with the original type.
@ -185,7 +185,7 @@ _[`Closure` documentation](https://rustwasm.github.io/wasm-bindgen/api/wasm_bind
## [`js-sys`](https://crates.io/crates/js-sys)
The `js-sys` crate provides bindings / imports of JavaScript's standard, built-in objects, including
The `js-sys` crate provides bindings/imports of JavaScript's standard, built-in objects, including
their methods and properties.
This does not include any web APIs as this is what [`web-sys`](./web-sys.mdx) is for!
@ -204,8 +204,9 @@ There are three main interfaces in this crate currently:
1. [`JsFuture`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/struct.JsFuture.html) -
A type that is constructed with a [`Promise`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Promise.html)
and can then be used as a `Future<Output=Result<JsValue, JsValue>>`. This Rust future will resolve
or reject with the value coming out of the `Promise`.
and can then be used as a `Future<Output=Result<JsValue, JsValue>>`. This `Future` will resolve to `Ok` if
the `Promise` is resolved and `Err` if the `Promise` is rejected, containing the resolved or rejected
value from the `Promise` respectively.
2. [`future_to_promise`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/fn.future_to_promise.html) -
Converts a Rust `Future<Output=Result<JsValue, JsValue>>` into a

View File

@ -11,18 +11,18 @@ procedurally generated from browser WebIDL which is why some names are so long a
## Features in `web-sys`
The `web-sys` crate with all of it's features enabled can add lots of bloat to a Wasm application,
in order to get around this issue most types are feature gated so that you only include the types
you require for your application. Yew includes a number of features from `web-sys` and
exposes some types in it's public API, you will often need to add `web-sys` as a dependency yourself.
The `web-sys` crate with all of its features enabled can add lots of bloat to a Wasm application.
To get around this issue most types are feature gated so that you only include the types
you require for your application. Yew enables several features from `web-sys` and
exposes some types in its public API. You will often need to add `web-sys` as a dependency yourself.
## Inheritance in `web-sys`
In the [Simulating inheritance section](./wasm-bindgen.mdx#simulating-inheritance) you can read how in
general Rust provides an approach to simulate inheritance in JavaScript. This is very important in
`web-sys` as understanding what methods are available on a type means understanding it's inheritance.
`web-sys` as understanding what methods are available on a type means understanding its inheritance.
This section is going to look at a specific element and list out it's inheritance using Rust by
This section is going to look at a specific element and list out its inheritance using Rust by
calling [`Deref::deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html#tymethod.deref) until
the value is [`JsValue`](./wasm-bindgen.mdx#jsvalue):
@ -46,11 +46,11 @@ fn inheritance_of_text_area(text_area: HtmlTextAreaElement) {
let event_target: &EventTarget = node.deref();
// Notice we've moved from web-sys types now into built-in
// Notice we have moved from web-sys types now into built-in
// JavaScript types which are in the js-sys crate.
let object: &js_sys::Object = event_target.deref();
// Notice we've moved from js-sys type to the root JsValue from
// Notice we have moved from js-sys type to the root JsValue from
// the wasm-bindgen crate.
let js_value: &wasm_bindgen::JsValue = object.deref();
@ -79,13 +79,13 @@ _[Inheritance in `web-sys` in The `wasm-bindgen` Guide](https://rustwasm.github.
## The `Node` in `NodeRef`
Yew uses a [`NodeRef`](concepts/function-components/node-refs.mdx) in order to provide a way for keeping a reference to
Yew uses a [`NodeRef`](concepts/function-components/node-refs.mdx) to provide a way for keeping a reference to
a `Node` made by the [`html!`](concepts/html/introduction.mdx) macro. The `Node` part of `NodeRef` is referring to
[`web_sys::Node`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Node.html). The
`NodeRef::get` method will return a `Option<Node>` value, however, most of the time in Yew you want
to cast this value to a specific element so you can use it's specific methods. This casting
to cast this value to a specific element so you can use its specific methods. This casting
can be done using [`JsCast`](./wasm-bindgen.mdx#JsCast) on the `Node` value, if present, but Yew
provides the `NodeRef::cast` method to perform this casting for convenience and so that you don't
provides the `NodeRef::cast` method to perform this casting for convenience and so that you do not
necessarily have to include the `wasm-bindgen` dependency for the `JsCast` trait.
The two code blocks below do essentially the same thing, the first is using `NodeRef::cast` and
@ -128,8 +128,8 @@ fn with_jscast(node_ref: NodeRef) {
## JavaScript example to Rust
This section is to help show that any examples that use JavaScript to interact with the Web APIs
can be adapted and written using Rust with `web-sys`.
This section demonstrates examples of how JavaScript code which interact with the
Web APIs can be rewritten with `web-sys` in Rust.
### JavaScript example
@ -191,9 +191,9 @@ Document::new()
```
This version is much more verbose, but you will probably notice part of that is because of failure
types reminding us that some of these function calls have invariants that must be held otherwise will
cause a panic in Rust. Another part of the verbosity is the calls to `JsCast` in order to cast into
different types so that you can call it's specific methods.
types reminding us that some of these function calls have invariants that must be held, or otherwise will
cause a panic in Rust. Another part of the verbosity is the calls to `JsCast` to cast into
different types so that you can call its specific methods.
### Yew example
@ -204,7 +204,7 @@ the approach above:
```toml title=Cargo.toml
[dependencies.web-sys]
version = "0.3"
# We need to enable the `DomRect` feature in order to use the
# We need to enable the `DomRect` feature to use the
# `get_bounding_client_rect` method.
features = [
"console",
@ -239,7 +239,7 @@ html! {
## External libraries
`web-sys` is a raw binding to the Web API so it comes with some pain in Rust because it was not
designed with Rust or even a strong type system in mind, this is where community crates come in to
designed with Rust or even a strong type system in mind, this is where community crates
provide abstractions over `web-sys` to provide more idiomatic Rust APIs.
_[External libraries page](/community/external-libs)_

View File

@ -6,16 +6,16 @@ description: 'Using contexts to pass deeply nested data'
Usually, data is passed from a parent component to a child component via props.
But passing props can become verbose and annoying if you have to pass them through many components in the middle,
or if many components in your app need the same information. Context solve this problem by allowing a
or if many components in your app need the same information. Context solves this problem by allowing a
parent component to make data available to _any_ component in the tree below it, no matter how deep,
without having to pass it down with props.
## The problem with props: "Prop Drilling"
Passing [props](./function-components/properties.mdx) is a great way to pass data directly from parent to a child.
They become cumbersome to pass down through deeply nested component tree or when multiple components share the same data.
Passing [props](./function-components/properties.mdx) is a great way to pass data directly from a parent to a child.
They become cumbersome to pass down through deeply nested component trees or when multiple components share the same data.
A common solution to data sharing is lifting the data to a common ancestor and making the children take it as props.
However, this can lead to cases where the prop has to go through multiple components in order to reach the component needs it.
However, this can lead to cases where the prop has to go through multiple components to reach the component that needs it.
This situation is called "Prop Drilling".
Consider the following example which passes down the theme using props:
@ -84,14 +84,14 @@ fn App() -> Html {
We "drill" the theme prop through `Navbar` so that it can reach `Title` and `NavButton`.
It would be nice if `Title` and `NavButton`, the components that need access to the theme, can just access the theme
without having to pass it to them as prop. Contexts solve this problem by allowing a parent to pass data, theme in this case,
without having to pass it to them as a prop. Contexts solve this problem by allowing a parent to pass data, theme in this case,
to its children.
## Using Contexts
### Step 1: Providing the context
A context provider is required to consume the context. `ContextProvider<T>`, where `T` is the context struct is used as the provider.
A context provider is required to consume the context. `ContextProvider<T>`, where `T` is the context struct used as the provider.
`T` must implement `Clone` and `PartialEq`. `ContextProvider` is the component whose children will have the context available to them.
The children are re-rendered when the context changes. A struct is used to define what data is to be passed. The `ContextProvider` can be used as:
@ -140,30 +140,30 @@ See [docs for use_context](https://yew-rs-api.web.app/next/yew/functional/fn.use
We have 2 options to consume contexts in struct components:
- [Higher Order Components](../advanced-topics/struct-components/hoc.mdx): A higher order function component will consume the context and pass the data to the struct component which requires it.
- Consume context directly in struct component. See [example of struct component as a consumer](https://github.com/yewstack/yew/tree/master/examples/contexts/src/struct_component_subscriber.rs)
- [Higher Order Components](../advanced-topics/struct-components/hoc.mdx): A higher-order function component will consume the context and pass the data to the struct component which requires it.
- Consume context directly in the struct component. See [example of struct component as a consumer](https://github.com/yewstack/yew/tree/master/examples/contexts/src/struct_component_subscriber.rs)
## Use cases
Generally, if some data is needed by distant components in different parts of the tree, it's likely that context will help you.
Here's some examples of such cases:
Generally, if some data is needed by distant components in different parts of the tree, context will likely help you.
Here are some examples of such cases:
- **Theming**: You can put a context at the top of the app that holds your app theme and use it to adjust the visual appearance, as shown in the above example.
- **Current user account**: In many cases, components need to know the current logged-in user. You can use a context to provide the current user object to the components.
- **Current user account**: In many cases, components need to know the currently logged-in user. You can use a context to provide the current user object to the components.
### Considerations to make before using contexts
Contexts are very easy to use. That makes them very easy to misuse/overuse.
Just because you can use a context to share props to components multiple levels deep, doesn't mean that you should.
Just because you can use a context to share props to components multiple levels deep, does not mean that you should.
For example, you may be able to extract a component and pass that component as a child to another component. For example,
you may have a `Layout` component which takes `articles` as prop and passes it down to `ArticleList` component.
you may have a `Layout` component that takes `articles` as a prop and passes it down to `ArticleList` component.
You should refactor the `Layout` component to take children as props and display `<Layout> <ArticleList {articles} /> </Layout>`.
## Mutating context value a child
## Mutating the context value of a child
Because of Rust's ownership rules, a context cannot have a method that takes `&mut self` that can be called by children.
In order to mutate a context's value, we must combine it with a reducer. This is done by using the
To mutate a context's value, we must combine it with a reducer. This is done by using the
[`use_reducer`](https://yew-rs-api.web.app/next/yew/functional/fn.use_reducer.html) hook.
The [contexts example](https://github.com/yewstack/yew/tree/master/examples/contexts) demonstrates mutable contexts

View File

@ -55,7 +55,7 @@ fn App() -> Html {
Callbacks are also used to hook into DOM events.
For example here we define a callback that will be called when the user clicks the button:
For example, here we define a callback that will be called when the user clicks the button:
```rust
use yew::{function_component, html, Html, Properties, Callback};

View File

@ -2,7 +2,7 @@
title: 'Children'
---
`Children` is a special prop type that allows you to recieve nested `Html` that is provided like html child elements.
`Children` is a special prop type that allows you to receive nested `Html` that is provided like html child elements.
```rust
use yew::{function_component, html, Html, Properties, Children};

View File

@ -4,7 +4,7 @@ title: 'Communication between components'
## Parent to child messaging
Pass data as [props](./properties) that cause a rerender, this is the way to pass messages to children.
Pass data as [props](./properties) that cause a re-render, this is the way to pass messages to children.
## Child to parent messaging

View File

@ -4,7 +4,7 @@ title: 'Custom Hooks'
## Defining custom Hooks
Component's stateful logic can be extracted into reusable function by creating custom Hooks.
The stateful logic of a component can be extracted into reusable functions by creating custom Hooks.
Consider that we wish to create an event listener that listens to an event on the `window`
object.
@ -34,13 +34,13 @@ pub fn show_storage_changed() -> Html {
```
There's one problem with this code: the logic can't be reused by another component.
If we build another component which keeps track of the an event,
If we build another component that listens to a different event,
instead of copying the code, we can move the logic into a custom hook.
We'll start by creating a new function called `use_event`.
The `use_` prefix denotes that a function is a hook.
This function will take an event target, an event type and a callback.
All hooks must be marked by `#[hook]` to function as as hook.
This function will take an event target, an event type, and a callback.
All hooks must be marked by `#[hook]` on their function definition.
```rust
use web_sys::{Event, EventTarget};
@ -58,7 +58,7 @@ where
}
```
This is a simple hook which can be created by composing built-in hooks. For this example, we'll use the
This simple hook can be created by composing built-in hooks. For this example, we'll use the
`use_effect_with_deps` hook, so an event listener can be recreated when the hook arguments change.
```rust

View File

@ -5,21 +5,21 @@ slug: /concepts/function-components/hooks
## Hooks
Hooks are functions that let you store state and perform side-effects.
Hooks are functions that let you store state and perform side effects.
Yew comes with a few pre-defined Hooks. You can also create your own or discover many [community made hooks](/community/awesome#hooks).
Yew comes with a few pre-defined hooks. You can also create your own or discover many [community-made hooks](/community/awesome#hooks).
## Rules of hooks
1. A hook function name always has to start with `use_`
2. Hooks can only be used in the following locations:
- Top level of a function / hook.
- Blocks inside a function / hook, given it's not already branched.
- In the condition of a top level `if` expression inside a function / hook.
- In the scrutinee of a top level `match` expression inside a function / hook.
- Top-level of a function/hook.
- Blocks inside a function/hook, given it is not already branched.
- In the condition of a top-level `if` expression inside a function/hook.
- In the scrutinee of a top-level `match` expression inside a function/hook.
3. Hooks must be called in the same order for every render. Returning early is only allowed when using [Suspense](../../suspense.mdx)
These rules are enforced by either compile time or run-time errors.
These rules are enforced by either compile-time or run-time errors.
### Pre-defined Hooks
@ -48,4 +48,4 @@ See the [Defining custom hooks](concepts/function-components/hooks/custom-hooks.
## Further reading
- The React documentation has a section on [React hooks](https://reactjs.org/docs/hooks-intro.html).
These are not exactly the same as Yew's hooks, but the underlying concept is similar.
These are not the same as Yew's hooks, but the underlying concept is similar.

View File

@ -3,13 +3,13 @@ title: 'Function Components'
slug: /concepts/function-components
---
Lets revisit this previous statement:
Let's revisit this previous statement:
> Yew centrally operates on the idea of keeping everything that a reusable piece of
> UI may need in one place - rust files.
We will refine this statement, by introducing the concept that will define the logic and
presentation behaviour of an application: "components".
presentation behavior of an application: "components".
## What are Components?
@ -21,7 +21,7 @@ They:
- Can have their own state
- Compute pieces of HTML visible to the user (DOM)
## Two flavours of Yew Components
## Two flavors of Yew Components
You are currently reading about function components - the recommended way to write components
when starting with Yew and when writing simple presentation logic.
@ -55,7 +55,7 @@ fn App() -> Html {
When rendering, Yew will build a virtual tree of these components.
It will call the view function of each (function) component to compute a virtual version (VDOM) of the DOM
that you as the library user see as the `Html` type.
For the previous example this would look like this:
For the previous example, this would look like this:
```xhtml
<App>
@ -71,6 +71,6 @@ This is what we call **rendering**.
:::note
Behind the scenes `Html` is just an alias for `VNode` - virtual node.
Behind the scenes, `Html` is just an alias for `VNode` - a virtual node.
:::

View File

@ -18,9 +18,9 @@ A type has to implement the `Properties` trait before it can be used as the prop
## Reactivity
Yew checks if props have changed when reconciling the vdom during rerendering, to know if nested components needs to be rerendered.
This way Yew can be considered a very reactive framework as changes from the parent will always be propagated downwards
and the view will never be out of sync from the data coming from props/state.
Yew checks if props have changed when reconciling the Virtual DOM during re-rendering, to know if nested components need to be re-rendered.
This way Yew can be considered a very reactive framework, as changes from the parent will always be propagated downward,
and the view will never be out of sync with the data coming from props/state.
:::tip
@ -102,7 +102,7 @@ fn App() -> Html {
## Derive macro field attributes
When deriving `Properties` all fields are required by default.
The following attributes allow you to give your props default values which will be used when parent has not set them.
The following attributes allow you to give your props default values which will be used when the parent has not set them.
:::tip
Attributes aren't visible in Rustdoc generated documentation.
@ -294,7 +294,7 @@ These include, but are not limited to:
See that crate to learn more.
2. Using interior mutability. <br />
**Why is this bad?** Interior mutability (such as with `RefCell`, `Mutex`, etc.) should
_generally_ be avoided. It can cause problems with re-renders (Yew doesn't know when state has changed)
_generally_ be avoided. It can cause problems with re-renders (Yew doesn't know when the state has changed)
so you may have to manually force a render. Like all things, it has its place. Use it with caution.
3. You tell us. Did you run into an edge-case you wish you knew about earlier? Feel free to create an issue
or PR a fix to this documentation.

View File

@ -3,11 +3,11 @@ title: 'Pure Components'
---
A function component is considered [pure] when the returned `Html` is deterministically derived
from its props, and its view function mutates no state or has other side-effects.
from its props when its view function does not mutate its state or has other side effects.
[pure]: https://en.wikipedia.org/wiki/Pure_function
For example below is a pure component. For a given prop `is_loading` it will always result in the same `Html` without any side effects.
The example below is a pure component. For a given prop `is_loading` it will always result in the same `Html` without any side effects.
```rust
use yew::{Properties, function_component, Html, html};
@ -35,5 +35,5 @@ as a normal function returning `Html` and avoid a bit of overhead for Yew, relat
## Impure components
You might wonder if a component can be impure if it does not use any globals, since its just a function that is called every render.
You might wonder if a component can be impure if it does not use any globals, since it is just a function that is called every render.
This is where the next topic comes in - [hooks](./hooks)

View File

@ -4,7 +4,7 @@ title: 'State'
## General view of how to store state
This table can be used as a guide when deciding what state storing type fits best for your use case:
This table can be used as a guide when deciding what state-storing type fits best for your use case:
| Hook | Type | Rerender when? | Scope |
| ------------------------ | -------------------------- | ---------------------------- | ------------------- |

View File

@ -14,12 +14,11 @@ When pushing a string to the set, `Classes` ensures that there is one element
for every class even if a single string might contain multiple classes.
`Classes` can also be merged by using `Extend` (i.e.
`classes1.extend(classes2)`) or `push()` (i.e. `classes1.push(classes2)`). In
fact, anything that implements `Into<Classes>` can be used to push new classes
to the set.
`classes1.extend(classes2)`) or `push()` (i.e. `classes1.push(classes2)`).
Any type that implements `Into<Classes>` can be pushed onto an existing `Classes`.
The macro `classes!` is a convenient macro that creates one single `Classes`.
Its input accepts a comma separated list of expressions. The only requirement
Its input accepts a comma-separated list of expressions. The only requirement
is that every expression implements `Into<Classes>`.
<Tabs>

View File

@ -55,7 +55,7 @@ html!{
## Nested
Components can be passed children if they have a `children` field in their `Properties`.
Components can accept child components/elements if they have a `children` field in their `Properties`
```rust title="parent.rs"
use yew::prelude::*;
@ -121,7 +121,7 @@ html! {
## Nested Children with Props
Nested component properties can be accessed and mutated if the containing component types its children. In the following example, the `List` component can wrap `ListItem` components. For a real world example of this pattern, check out the `yew-router` source code. For a more advanced example, check out the `nested-list` example in the main yew repository.
Nested component properties can be accessed and mutated if the containing component types its children. In the following example, the `List` component can wrap `ListItem` components. For a real-world example of this pattern, check out the `yew-router` source code. For a more advanced example, check out the `nested-list` example in the main yew repository.
```rust
use std::rc::Rc;

View File

@ -12,7 +12,7 @@ There are many reasons why you might want to create or manage DOM nodes manually
when integrating with JS libraries that can cause conflicts with managed components.
Using `web-sys`, you can create DOM elements and convert them into a `Node` - which can then be
used as a `Html` value using `VRef`:
used as an `Html` value using `VRef`:
```rust
use web_sys::{Element, Node};
@ -44,8 +44,8 @@ fn MyComponent() -> Html {
## Dynamic tag names
When building a higher-order component you might find yourself in a situation where the element's tag name isn't static.
For example, you might have a `Title` component which can render anything from `h1` to `h6` depending on a level prop.
When building a higher-order component you might find yourself in a situation where the element's tag name is not static.
For example, you might have a `Title` component that can render anything from `h1` to `h6` depending on a level prop.
Instead of having to use a big match expression, Yew allows you to set the tag name dynamically
using `@{name}` where `name` can be any expression that returns a string.
@ -75,7 +75,7 @@ html! {
};
```
This will result in **HTML** that's functionally equivalent to this:
This will result in **HTML** that is functionally equivalent to this:
```html
<div hidden>This div is hidden.</div>
@ -104,7 +104,7 @@ This will result in the following **HTML**:
## String-like attributes
But apart from a select few boolean attributes, you will probably be dealing with a lot of string-like HTML attributes and Yew has a few option for those
But apart from a select few boolean attributes, you will probably be dealing with a lot of string-like HTML attributes and Yew has a few options to pass string-like values to components.
```rust
use yew::{html, virtual_dom::AttrValue};
@ -138,7 +138,7 @@ html! {
};
```
If the attribute is set to `None`, the attribute won't be set in the DOM.
If the attribute is set to `None`, the attribute will not be set in the DOM.
## Relevant examples

View File

@ -16,7 +16,7 @@ below, see [Manual event listener](#manual-event-listener).
:::tip
All the event types mentioned in the following table are re-exported under `yew::events`.
Using the types from `yew::events` makes it easier to ensure version compatibility than
if you were to manually include `web-sys` as a dependency in your crate because you won't
if you were to manually include `web-sys` as a dependency in your crate because you will not
end up using a version which conflicts with the version that Yew specifies.
:::
@ -41,8 +41,8 @@ listens for `click` events. See the end of this page for a [full list of availab
Events dispatched by Yew follow the virtual DOM hierarchy when bubbling up to listeners. Currently, only the bubbling phase
is supported for listeners. Note that the virtual DOM hierarchy is most often, but not always, identical to the actual
DOM hierarchy. The distinction is important when working with [portals](../../advanced-topics/portals.mdx) and other
more advanced techniques. The intuition for well implemented components should be that events bubble from children
to parents, so that the hierarchy in your coded `html!` is the one observed by event handlers.
more advanced techniques. The intuition for well-implemented components should be that events bubble from children
to parents. In this way the hierarchy in your coded `html!` is the one observed by event handlers.
If you are not interested in event bubbling, you can turn it off by calling
@ -50,20 +50,20 @@ If you are not interested in event bubbling, you can turn it off by calling
yew::set_event_bubbling(false);
```
_before_ starting your app. This speeds up event handling, but some components may break from not receiving events they expect.
_before_ starting your app. This speeds up event handling, but some components may break from not receiving the events they expect.
Use this with care!
## Event delegation
It can be surprising that event listeners are _not_ directly registered on the element where they are rendered. Instead, events
are delegated from the subtree root of the Yew app. Still, events are delivered in their native form, and no synthetic
form is created. This can lead to mismatches between the event you'd expect in html listeners and those showing up in Yew.
form is created. This can lead to mismatches between the event you would expect in HTML listeners and those showing up in Yew.
- [`Event::current_target`] points to the Yew subtree root instead of the element the listener is added on. Use
[`NodeRef`](../function-components/node-refs.mdx) if you want access to the underlying `HtmlElement`.
- [`Event::event_phase`] is always [`Event::CAPTURING_PHASE`]. Internally, the event will behave as if it was in the bubbling
phase, the event propagation is replayed and the event [bubbles _up_](#event-bubbling), i.e. event listeners higher up in
the virtual DOM will trigger _after_ event listeners below them. Currently, capturing listeners are not supported by Yew.
the virtual DOM will trigger _after_ event listeners below them. Currently, capturing listeners is not supported by Yew.
This also means that events registered by Yew will usually fire before other event listeners.
@ -88,8 +88,8 @@ them here. Calling [`web_sys::Event::target`](https://rustwasm.github.io/wasm-bi
on an event returns an optional [`web_sys::EventTarget`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.EventTarget.html)
type, which might not seem very useful when you want to know the value of your input element.
In all the approaches below we are going to tackle the same problem, so it's clear where the approach
differs opposed to the problem at hand.
In all the approaches below we are going to tackle the same problem, so it is clear where the approach
differs as opposed to the problem at hand.
**The Problem:**

View File

@ -5,7 +5,7 @@ title: 'Fragments'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
The `html!` macro always requires a single root node. In order to get around this restriction, you
The `html!` macro always requires a single root node. To get around this restriction, you
can use an "empty tag" (these are also called "fragments").
<Tabs>

View File

@ -9,7 +9,7 @@ import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
The `html!` macro allows you to write HTML and SVG code declaratively. It is similar to JSX
(an extension to JavaScript which allows you to write HTML-like code inside of JavaScript).
(an extension to JavaScript that allows you to write HTML-like code inside of JavaScript).
**Important notes**
@ -17,7 +17,7 @@ The `html!` macro allows you to write HTML and SVG code declaratively. It is sim
[fragments](./fragments.mdx) or [iterators](./../html/lists.mdx))
2. An empty `html! {}` invocation is valid and will not render anything
3. Literals must always be quoted and wrapped in braces: `html! { <p>{ "Hello, World" }</p> }`
4. The `html!` macro will make all tag names lower case. To use upper case characters (which are required for some SVG elements) use [dynamic tag names](concepts/html/elements.mdx#dynamic-tag-names): `html! { <@{"myTag"}></@> }`
4. The `html!` macro will make all tag names lowercase. To use upper case characters (which are required for some SVG elements) use [dynamic tag names](concepts/html/elements.mdx#dynamic-tag-names): `html! { <@{"myTag"}></@> }`
:::note
The `html!` macro can reach the default recursion limit of the compiler. If you encounter compilation errors,

View File

@ -51,11 +51,11 @@ html! {
## Keyed lists
A keyed list is an optimized list that has keys on **all** children.
`key` is a special prop provided by Yew which gives an html element or component a unique identifier
which is used for optimization purposes inside Yew.
`key` is a special prop provided by Yew that gives an HTML element or component a unique identifier
that is used for optimization purposes inside Yew.
:::caution
Key has to be unique only in each list, in constrast to the global uniqueness of html `id`s. It must not depend on the order of the list.
Key has to be unique only in each list, in contrast to the global uniqueness of HTML `id`s. It must not depend on the order of the list.
:::
It is always recommended to add keys to lists.
@ -81,7 +81,7 @@ html! {
### Performance increases
We have [Keyed list](https://github.com/yewstack/yew/tree/master/examples/keyed_list) example that lets you test the performance improvements, but here is rough rundown:
We have [Keyed list](https://github.com/yewstack/yew/tree/master/examples/keyed_list) example that lets you test the performance improvements, but here is a rough rundown:
1. Go to [Keyed list](https://github.com/yewstack/yew/tree/master/examples/keyed_list) hosted demo
2. Add 500 elements.
@ -92,14 +92,14 @@ We have [Keyed list](https://github.com/yewstack/yew/tree/master/examples/keyed_
7. Reverse the list.
8. Look at "The last rendering took Xms" (At the time of writing this it was ~30ms)
So just at the time of writing this, for 500 components its a x2 increase of speed.
So just at the time of writing this, for 500 components it is a 2x increase of speed.
### Detailed explanation
Usually you just need a key on every list item when you iterate and the order of data can change.
Usually, you just need a key on every list item when you iterate and the order of data can change.
It's used to speed up the reconciliation process when re-rendering the list.
Without keys, lets assume you iterate through `["bob","sam","rob"]`, ending up with the html:
Without keys, assume you iterate through `["bob", "sam", "rob"]`, ending up with the HTML:
```html
<div id="bob">My name is Bob</div>
@ -107,16 +107,16 @@ Without keys, lets assume you iterate through `["bob","sam","rob"]`, ending up w
<div id="rob">My name is rob</div>
```
Then on the next render, if your list changed to `["bob","rob"]`, yew could delete
Then on the next render, if your list changed to `["bob", "rob"]`, yew could delete
the element with id="rob" and update id="sam" to be id="rob"
If you had added a key to each element, the initial html would be the same, but after
the render with the modified list, `["bob","rob"]`, yew would just delete the second
html element and leave the rest untouched since it can use the keys to associate them.
If you had added a key to each element, the initial HTML would be the same, but after
the render with the modified list, `["bob", "rob"]`, yew would just delete the second
HTML element and leave the rest untouched since it can use the keys to associate them.
If you ever encounter a bug/"feature" where you switch from one component to another but both have a div as the highest rendered element.
Yew reuses the rendered html div in those cases as an optimization.
If you need that div to be recreated instead of reused, then you can add different keys and they wont be reused
Yew reuses the rendered HTML div in those cases as an optimization.
If you need that div to be recreated instead of reused, then you can add different keys and they will not be reused.
## Further reading

View File

@ -9,7 +9,7 @@ If expressions resolve to types that implement `Display`, they will be converted
String literals create `Text` nodes, which are treated as strings by the browser. Hence, even if the expression contains a `<script>` tag you can't fall for XSS and such security issues, unless of course you wrap the expression in a `<script>` block.
:::
All display text must be enclosed by `{}` blocks because text is handled as an expression. This is
All display text must be enclosed by `{}` blocks because the text is handled as an expression. This is
the largest deviation from normal HTML syntax that Yew makes.
```rust

View File

@ -42,15 +42,15 @@ enum Route {
A `Route` is paired with a `<Switch />` component, which finds the variant whose path matches the browser's
current URL and passes it to the `render` callback. The callback then decides what to render. In case no path is
matched, the router navigates to the path with `not_found` attribute. If no route is specified, nothing is rendered, and
a message is logged to console stating that no route was matched.
a message is logged to the console stating that no route was matched.
Most of yew-router's components, in particular `<Link />` and `<Switch />`, must be (grand-)children of one of the Router components
(e.g. `<BrowserRouter />`). You usually only need a single Router in your app, most often rendered immediately by your most top-level `<App />`
component. The Router registers a context, which is needed for Links and Switches to function. An example is shown below.
:::caution
When using `yew-router` in browser environment, `<BrowserRouter />` is highly recommended.
You can find other router flavours in the [API Reference](https://docs.rs/yew-router/).
When using `yew-router` in a browser environment, `<BrowserRouter />` is highly recommended.
You can find other router flavors in the [API Reference](https://docs.rs/yew-router/).
:::
```rust
@ -130,8 +130,8 @@ fn switch(route: Route) -> Html {
```
:::note
You can have a normal `Post` variant instead of `Post {id: String}` too. For example when `Post` is rendered
with another router, the field can then be redundant as the other router is able to match and handle the path. See the
You can have a normal `Post` variant instead of `Post {id: String}` too. For example, when `Post` is rendered
with another router, the field can then be redundant as the other router can match and handle the path. See the
[Nested Router](#nested-router) section below for details
:::
@ -177,7 +177,7 @@ They can be retrieved by hooks or convenient functions on `ctx.link()`.
A `<Link />` renders as an `<a>` element, the `onclick` event handler will call
[preventDefault](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault), and push the targeted page to the
history and render the desired page, which is what should be expected from a Single Page App. The default onclick of a
history and render the desired page, which is what should be expected from a Single Page App. The default `onclick` of a
normal anchor element would reload the page.
The `<Link />` component also passes its children to the `<a>` element. Consider it a replacement of `<a/>` for in-app
@ -196,12 +196,12 @@ Struct variants work as expected too:
#### Navigator API
Navigator API is provided for both function components and struct components. They enable callbacks to change the
route. An `Navigator` instance can be obtained in either cases to manipulate the route.
route. A `Navigator` instance can be obtained in either case to manipulate the route.
##### Function Components
For function components, the `use_navigator` hook re-renders the component when the underlying navigator provider changes.
Here's how to implement a button that navigates to the `Home` route when clicked.
Here is how to implement a button that navigates to the `Home` route when clicked.
```rust ,ignore
#[function_component(MyComponent)]
@ -218,17 +218,17 @@ pub fn my_component() -> Html {
```
:::caution
The example here uses `Callback::from`. Use a normal callback if the target route can be the same with the route
the component is in, or just to play safe. For example, when you have a logo button on every page, that goes back to
home when clicked, clicking that button twice on home page causes the code to panic because the second click pushes an
identical Home route and the `use_navigator` hook won't trigger a re-render.
The example here uses `Callback::from`. Use a normal callback if the target route can be the same as the route
the component is in, or just to play safe. For example, consider a logo button on every page that goes back to the
home page when clicked. Clicking that button twice on the home page causes the code to panic because the second click pushes an
identical Home route and the `use_navigator` hook will not trigger a re-render.
:::
If you want to replace the current location instead of pushing a new location onto the stack, use `navigator.replace()`
instead of `navigator.push()`.
You may notice `navigator` has to move into the callback, so it can't be used again for other callbacks. Luckily `navigator`
implements `Clone`, here's for example how to have multiple buttons to different routes:
You may notice `navigator` has to move into the callback, so it cannot be used again for other callbacks. Luckily `navigator`
implements `Clone`, here is for example how to have multiple buttons for different routes:
```rust ,ignore
use yew::prelude::*;
@ -274,7 +274,7 @@ pub fn nav_items() -> Html {
##### Struct Components
For struct components, the `Navigator` instance can be obtained through the `ctx.link().navigator()` API. The rest is
identical with the function component case. Here's an example of a view function that renders a single button.
identical to the function component case. Here is an example of a view function that renders a single button.
```rust ,ignore
fn view(&self, ctx: &Context<Self>) -> Html {
@ -290,7 +290,7 @@ fn view(&self, ctx: &Context<Self>) -> Html {
`yew-router` also provides a `<Redirect />` component in the prelude. It can be used to achieve similar effects as the
navigator API. The component accepts a
`to` attribute as the target route. When a `<Redirect/>` is rendered users will be redirect to the route specified in props.
`to` attribute as the target route. When a `<Redirect/>` is rendered users will be redirected to the route specified in props.
Here is an example:
```rust ,ignore
@ -310,7 +310,7 @@ fn some_page() -> Html {
:::tip `Redirect` vs `Navigator`, which to use
The Navigator API is the only way to manipulate route in callbacks.
While `<Redirect />` can be used as return values in a component. You might also want to use `<Redirect />` in other
While `<Redirect />` can be used as return values in a component. You might also want to use `<Redirect />` in another
non-component context, for example in the switch function of a [Nested Router](#nested-router).
:::
@ -350,13 +350,13 @@ fn create(ctx: &Context<Self>) -> Self {
#### Specifying query parameters when navigating
In order to specify query parameters when navigating to a new route, use either `navigator.push_with_query` or
the `navigator.replace_with_query` functions. It uses `serde` to serialize the parameters into query string for the URL so
any type that implements `Serialize` can be passed. In its simplest form this is just a `HashMap` containing string
the `navigator.replace_with_query` functions. It uses `serde` to serialize the parameters into a query string for the URL so
any type that implements `Serialize` can be passed. In its simplest form, this is just a `HashMap` containing string
pairs.
#### Obtaining query parameters for current route
#### Obtaining query parameters for the current route
`location.query` is used to obtain the query parameters. It uses `serde` to deserialize the parameters from query string
`location.query` is used to obtain the query parameters. It uses `serde` to deserialize the parameters from the query string
in the URL.
## Nested Router
@ -383,7 +383,7 @@ digraph {
-->
<!--
Also the dark themed version:
Also the dark-themed version:
digraph {
bgcolor=transparent
node [shape=box style="filled, rounded" fillcolor=grey color=white fontcolor=white]
@ -409,12 +409,12 @@ import ThemedImage from '@theme/ThemedImage'
}}
/>
The nested `SettingsRouter` handles all urls that start with `/settings`. Additionally, it redirects urls that are not
The nested `SettingsRouter` handles all URLs that start with `/settings`. Additionally, it redirects URLs that are not
matched to the main `NotFound` route. So `/settings/gibberish` will redirect to `/404`.
:::caution
Though note that this is still work in progress so the way we do this is not final
Though note that this is still a work in progress so the way we do this is not final
:::
@ -494,8 +494,8 @@ prefixed with the basename and all switches will strip the basename before
trying to parse the path into a `Routable`.
If a basename prop is not supplied to the Router component, it will use
the href attribute of the `<base />` element in your html file and
fallback to `/` if no `<base />` presents in the html file.
the href attribute of the `<base />` element in your HTML file and
fallback to `/` if no `<base />` is present in the HTML file.
## Relevant examples

View File

@ -32,7 +32,7 @@ cd yew-app
### Run a hello world example
To verify the Rust environment is setup, run the initial project using `cargo run`. You should see
To verify the Rust environment is set up, run the initial project using `cargo run`. You should see
a "Hello World!" message.
```bash
@ -61,8 +61,8 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
:::info
You only need feature `csr` if you are building an application.
It will enable the `Renderer` and all client-side rendering related code.
You only need the feature `csr` if you are building an application.
It will enable the `Renderer` and all client-side rendering-related code.
If you are making a library, do not enable this feature as it will pull in
client-side rendering logic into the server-side rendering bundle.
@ -74,7 +74,7 @@ in the `dev-dependencies` instead.
#### Update main.rs
We need to generate a template which sets up a root Component called `App` which renders a button
We need to generate a template that sets up a root Component called `App` which renders a button
that updates its value when clicked. Replace the contents of `src/main.rs` with the following code.
:::note
@ -136,6 +136,6 @@ Trunk will rebuild your application if you modify any of its source code files.
## Congratulations
You have now successfully setup your Yew development environment, and built your first web application.
You have now successfully set up your Yew development environment, and built your first web application.
Experiment with this application and review the [examples](./examples.mdx) to further your learning.

View File

@ -10,7 +10,7 @@ For more details including a list of examples, refer to the [README].
:::note
Most of the examples have a live deployment that can be found at https://examples.yew.rs/<example_name>.
Click the shield on their individual README page in their respective sub-folder to navigate to the live demo.
Click the shield on their README page in their respective sub-folder to navigate to the live demo.
:::
[examples]: https://github.com/yewstack/yew/tree/master/examples

View File

@ -11,9 +11,9 @@ bundler for Rust.
To install Rust, follow the [official instructions](https://www.rust-lang.org/tools/install).
:::important
The minimum supported Rust version (MSRV) for Yew is `1.56.1`. Older versions can cause unexpected
issues accompanied by incomprehensible error messages. You can check your toolchain version using
`rustup show` (under "active toolchain") or alternatively `rustc --version`. To update your
The minimum supported Rust version (MSRV) for Yew is `1.60.0`. Older versions will not compile.
You can check your toolchain version using
`rustup show` (under "active toolchain") or `rustc --version`. To update your
toolchain, run `rustup update`.
:::
@ -29,11 +29,11 @@ rustup target add wasm32-unknown-unknown
## Install Trunk
Trunk is the recommended tool for managing deployment and packaging, and is used throughout the
Trunk is the recommended tool for managing deployment and packaging and is used throughout the
documentation and examples.
```shell
# note that this might take a while to install, because it compiles everything from scratch
# note that this might take a while to install because it compiles everything from scratch
# Trunk also provides prebuilt binaries for a number of major package managers
# See https://trunkrs.dev/#install for further details
cargo install --locked trunk
@ -49,5 +49,5 @@ There are options other than Trunk that may be used for bundling Yew application
## Next steps
With your development environment setup, you can now either proceed with the reading the documentation.
If you like to learn by getting your hands dirty, we recommend you check out our [tutorial](../tutorial)
With your development environment setup, you can now either proceed with reading the documentation.
If you like to learn by getting your hands dirty, we recommend you check out our [tutorial](../tutorial).

View File

@ -7,10 +7,10 @@ A proposal for integrated CSS support can be found here:
This contains a lot of discussion about how to best integrate CSS support into Yew.
Currently, the approach we've adopted is to encourage developers to build a number of systems, before
Currently, the approach we have adopted is to encourage developers to build many systems, before
adopting the most popular one.
The community are currently developing a number of projects to make it easy to add styles to
The community is currently developing several projects to make it easy to add styles to
projects. A few are given below:
#### Component Libraries

View File

@ -12,7 +12,7 @@ In JavaScript, `console.log()` is used to log to the browser console. Some optio
### [`wasm-logger`](https://crates.io/crates/wasm-logger)
`wasm-logger` crate integrates with [`log`](https://crates.io/crates/log) crate to send the log level, source line and filename to the browser console.
`wasm-logger` crate integrates with [`log`](https://crates.io/crates/log) crate to send the log level, source line, and filename to the browser console.
```rust ,ignore
use log::info;
@ -89,7 +89,7 @@ Some past articles on the state of debugging in WebAssembly in Rust can be found
\[Dec 2019\] [Chrome DevTools update](https://developers.google.com/web/updates/2019/12/webassembly#the_future)
> There is still quite a bit of work to do though. For example, on the tooling side, Emscripten \(Binaryen\) and wasm-pack \(wasm-bindgen\) dont support updating DWARF information on transformations they perform yet.
> There is still quite a bit of work to do though. For example, on the tooling side, Emscripten \(Binaryen\) and wasm-pack \(wasm-bindgen\) does not support updating DWARF information on transformations they perform yet.
\[2020\] [Rust Wasm debugging guide](https://rustwasm.github.io/book/reference/debugging.html#using-a-debugger)

View File

@ -14,21 +14,21 @@ It should only be used for testing the release build during development
## Server configuration
### Serving `index.html` as fallback
### Serving `index.html` as a fallback
If the application uses the [Yew router](concepts/router.mdx), you must configure the server to return the `index.html` when asked for a file that it does not have.
An application with Yew router is built as a [Single Page Application (SPA)](https://developer.mozilla.org/en-US/docs/Glossary/SPA). When the user navigates to a URL from within a running client, the router interprets the URL and routes to that page.
But on a fresh load, such as when navigating to the page by entering it in the address bar or refreshing the page, all of these actions are handled by the browser itself, outside the running application. The browser makes a direct request to the server for that URL, bypassing the router. A wrongly configured server would return with status 404 - Not Found.
But on a fresh load, such as when navigating to the page by entering it in the address bar or refreshing the page, all of these actions are handled by the browser itself, outside the running application. The browser makes a direct request to the server for that URL, bypassing the router. A wrongly configured server would return with the status 404 - Not Found.
By returning `index.html` instead, the app loads as it normally would as if request was for `/`, until the router notices that the the route is `/show/42` and displays the appropriate contents.
By returning `index.html` instead, the app loads as it normally would, as if the request was for `/` until the router notices that the route is `/show/42` and displays the appropriate contents.
### Configuring correct MIME-type for Web Assembly asset.
The WASM files must be served with the [Content-Type header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) set to `application/wasm` MIME-type.
Most servers and hosting services already do this by default. If yours doesn't, consult its documentation. An incorrect MIME-type will, in most web browsers, result in an error similar to the following:
Most servers and hosting services already do this by default. If yours does not, consult its documentation. An incorrect MIME type will, in most web browsers, result in an error similar to the following:
```ignore
`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:
@ -41,5 +41,5 @@ By default, trunk will assume that your site is being served at `/` and build th
## Customizing behavior using environment variables
It's common to customize the build environment by using environment variables. Since the app is run in browser, we can't read the environment variables at runtime.
The [`std::env!`](https://doc.rust-lang.org/std/macro.env.html) macro can be used to obtain a value of an environment variables at compile time.
It is common to customize the build environment by using environment variables. Since the app is run in a browser, we cannot read the environment variables at runtime.
The [`std::env!`](https://doc.rust-lang.org/std/macro.env.html) macro can be used to obtain a value of an environment variable at compile time.

View File

@ -4,14 +4,14 @@ description: 'Testing your app'
---
:::info
We're working on making it easy to test components, but this is currently a work in progress.
We are working on making it easy to test components, but this is currently a work in progress.
Support for [shallow rendering](https://github.com/yewstack/yew/issues/1413) can be found in the GitHub repository.
:::
## Snapshot testing
Yew exposes the `yew::tests::layout_tests` module to facilitate with snapshot testing of components.
Yew exposes the `yew::tests::layout_tests` module to facilitate snapshot testing of components.
:::important contribute
Help improve the documentation for snapshot testing.
@ -20,6 +20,6 @@ Help improve the documentation for snapshot testing.
## wasm_bindgen_test
The Rust/WASM working group maintains a crate called [`wasm_bindgen_test`](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html)
which allows you to run tests in a browser in similar fashion to how the built-in `#[test]` procedural macro works.
which allows you to run tests in a browser in a similar fashion to how the built-in `#[test]` procedural macro works.
More information is given in the [Rust Wasm working group's documentation](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html)
for this module.

View File

@ -24,12 +24,12 @@ get an overview of the talks and watch them all from one page.
### Prerequisites
This tutorial assumes you're already familiar with Rust. If you're new to Rust,
This tutorial assumes you are already familiar with Rust. If you are new to Rust,
the free [Rust Book](https://doc.rust-lang.org/book/ch00-00-introduction.html) offers a great starting point for
beginners and continues to be an excellent resource even for experienced Rust developers.
Ensure the latest version of Rust is installed by running `rustup update` or by
[installing rust](https://www.rust-lang.org/tools/install) if you haven't already done so.
[installing rust](https://www.rust-lang.org/tools/install) if you have not already done so.
After installing Rust, you can use Cargo to install `trunk` by running:
@ -53,7 +53,7 @@ cd yew-app
```
To verify the Rust environment is set up properly, run the initial project using the cargo build tool.
After output about the build process, you should see the expected "Hello, world!" message.
After the output about the build process, you should see the expected "Hello, world!" message.
```bash
cargo run
@ -76,8 +76,8 @@ yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
:::info
You only need feature `csr` if you are building an application.
It will enable the `Renderer` and all client-side rendering related code.
You only need the feature `csr` if you are building an application.
It will enable the `Renderer` and all client-side rendering-related code.
If you are making a library, do not enable this feature as it will pull in
client-side rendering logic into the server-side rendering bundle.
@ -122,7 +122,7 @@ trunk serve --open
Trunk will open your application in your default browser, watch the project directory and helpfully rebuild your
application if you modify any source files. If you are curious, you can run `trunk help` and `trunk help <subcommand>`
for more details on what's happening.
for more details on what is happening.
### Congratulations
@ -131,12 +131,12 @@ You have now successfully set up your Yew development environment and built your
## Building HTML
Yew makes use of Rust's procedural macros and provides us with a syntax similar to JSX (an extension to JavaScript
which allows you to write HTML-like code inside of JavaScript) to create the markup.
which allows you to write HTML-like code inside JavaScript) to create the markup.
### Converting classic HTML
Since we already have a pretty good idea of what our website will look like, we can simply translate our mental draft
into a representation compatible with `html!`. If you're comfortable writing simple HTML, you should have no problem
into a representation compatible with `html!`. If you are comfortable writing simple HTML, you should have no problem
writing marking inside `html!`. It is important to note that the macro does differ from HTML in a few ways:
1. Expressions must be wrapped in curly braces (`{ }`)
@ -193,8 +193,8 @@ Refresh the browser page, and you should see the following output displayed:
### Using Rust language constructs in the markup
A big advantage of writing markup in Rust is that we get all the coolness of Rust in our markup.
Now, instead of hardcoding the list of videos in the html, let's actually define them as a `Vec` of Rust objects.
We'll create a simple `struct` (in `main.rs` or any file of our choice) which will hold our data.
Now, instead of hardcoding the list of videos in the HTML, let's define them as a `Vec` of `Video` structs.
We create a simple `struct` (in `main.rs` or any file of our choice) that will hold our data.
```rust
struct Video {
@ -238,7 +238,7 @@ let videos = vec![
];
```
In order to display them, we need to convert these `Vec`s into `Html`. We can do that by creating an iterator,
To display them, we need to convert the `Vec` into `Html`. We can do that by creating an iterator,
mapping it to `html!` and collecting it as `Html`:
```rust ,ignore
@ -248,10 +248,10 @@ let videos = videos.iter().map(|video| html! {
```
:::tip
Keys on list items helps Yew keep track of which items have changed in the list, resulting in faster re-renders. [It is always recommended to use keys in lists](/concepts/html/lists.mdx#keyed-lists).
Keys on list items help Yew keep track of which items have changed in the list, resulting in faster re-renders. [It is always recommended to use keys in lists](/concepts/html/lists.mdx#keyed-lists).
:::
And finally we need to replace the hardcoded list of videos with the `Html` we created from data:
And finally, we need to replace the hardcoded list of videos with the `Html` we created from the data:
```rust ,ignore {6-10}
html! {
@ -276,7 +276,7 @@ Components are the building blocks of Yew applications. By combining components,
we build our application. By structuring our components for re-usability and keeping them generic, we will be able to use
them in multiple parts of our application without having to duplicate code or logic.
In fact, the `app` function we have been using so far is a component, called `App`. It is a "function component".
The `app` function we have been using so far is a component, called `App`. It is a "function component".
There are two different types of components in Yew.
1. Struct Components
@ -284,7 +284,7 @@ There are two different types of components in Yew.
In this tutorial, we will be using function components.
Now, let's split up our `App` component into smaller components. We'll begin by extracting the videos list into
Now, let's split up our `App` component into smaller components. We begin by extracting the videos list into
its own component.
```rust ,compile_fail
@ -312,13 +312,13 @@ fn videos_list(VideosListProps { videos }: &VideosListProps) -> Html {
Notice the parameters of our `VideosList` function component. A function component takes only one argument which
defines its "props" (short for "properties"). Props are used to pass data down from a parent component to a child component.
In this case, `VideosListProps` is a struct which defines the props.
In this case, `VideosListProps` is a struct that defines the props.
:::important
The struct used for props must implement `Properties` by deriving it.
:::
In order for the above code to compile, we need to modify the `Video` struct like:
For the above code to compile, we need to modify the `Video` struct like this:
```rust {1}
#[derive(Clone, PartialEq)]
@ -355,12 +355,12 @@ fn app() -> Html {
```
By looking at the browser window, we can verify that the lists are rendered as they should be.
We have moved the rendering logic of lists to its own component. This shortens the `App` components source code,
We have moved the rendering logic of lists to its component. This shortens the `App` components source code,
making it easier for us to read and understand.
### Making it interactive
The final goal here is to display the selected video. In order to do that, `VideosList` component needs to "notify" its
The final goal here is to display the selected video. To do that, `VideosList` component needs to "notify" its
parent when a video is selected, which is done via a `Callback`. This concept is called "passing handlers".
We modify its props to take an `on_click` callback:
@ -456,7 +456,7 @@ fn app() -> Html {
}
```
Don't worry about the `use_state` right now, we will come back to that later.
Do not worry about the `use_state` right now, we will come back to that later.
Note the trick we pulled with `{ for details }`. `Option<_>` implements `Iterator` so we can use it to display the only
element returned by the `Iterator` with a special `{ for ... }` syntax
[supported by the `html!` macro](concepts/html/lists).
@ -464,7 +464,7 @@ element returned by the `Iterator` with a special `{ for ... }` syntax
### Handling state
Remember the `use_state` used earlier? That is a special function, called a "hook". Hooks are used to "hook" into
lifecycle of a function component and perform actions. You can learn more about this hook, and others
the lifecycle of a function component and perform actions. You can learn more about this hook, and others
[here](concepts/function-components/hooks/introduction.mdx#pre-defined-hooks).
:::note
@ -473,8 +473,8 @@ Struct components act differently. See [the documentation](advanced-topics/struc
## Fetching data (using external REST API)
In a real world application, data will usually come from an API instead of being hardcoded. Let's fetch our
videos list from external source. For this we will need to add the following crates:
In a real-world application, data will usually come from an API instead of being hardcoded. Let's fetch our
videos list from an external source. For this we will need to add the following crates:
- [`gloo-net`](https://crates.io/crates/gloo-net)
For making the fetch call.
@ -553,12 +553,12 @@ fn app() -> Html {
```
:::note
We're using `unwrap`s here because this is a demo application. In a real world app, you would likely want to have
We are using `unwrap`s here because this is a demo application. In a real-world app, you would likely want to have
[proper error handling](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html).
:::
Now look at the browser to see everything working as expected... which would've been the case if it weren't for CORS.
In order to fix that, we need a proxy server. Luckily trunk provides that.
Now, look at the browser to see everything working as expected... which would have been the case if it were not for CORS.
To fix that, we need a proxy server. Luckily trunk provides that.
Update the following line:
@ -583,13 +583,13 @@ Congratulations! Youve created a web application that fetches data from an ex
## What's next
Obviously, this application is very far from perfect or useful. After going through this tutorial,
This application is very far from perfect or useful. After going through this tutorial,
you can use it as a jumping-off point to explore more advanced topics.
### Styles
Our apps look very ugly. There's no CSS, or any kind of styles.
Unfortunately, Yew doesn't offer a built-in way to style components. See [Trunk's assets](https://trunkrs.dev/assets/)
Our apps look very ugly. There is no CSS or any kind of style.
Unfortunately, Yew does not offer a built-in way to style components. See [Trunk's assets](https://trunkrs.dev/assets/)
to learn how to add style sheets.
### More libraries
@ -599,5 +599,5 @@ See [external libraries](/community/external-libs) for more details.
### Learning more about Yew
Read our [official documentation](../getting-started/introduction.mdx). It explains a lot of concepts in much more details.
To learn more about our the Yew API, see our [API docs](https://docs.rs/yew).
Read our [official documentation](../getting-started/introduction.mdx). It explains a lot of concepts in much more detail.
To learn more about the Yew API, see our [API docs](https://docs.rs/yew).