mirror of https://github.com/yewstack/yew
Improve grammar in website/docs (#3092)
* Improve grammar in website/docs * Futuresolo's changes to website/docs
This commit is contained in:
parent
8d308fb617
commit
9556266061
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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=).
|
||||
|
||||
:::
|
||||
|
|
|
@ -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`.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
:::
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 |
|
||||
| ------------------------ | -------------------------- | ---------------------------- | ------------------- |
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:**
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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\) don’t 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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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` component’s source code,
|
||||
We have moved the rendering logic of lists to its component. This shortens the `App` component’s 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! You’ve 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).
|
||||
|
|
Loading…
Reference in New Issue