mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
* change suffixes from md to mdx fix broken links for English locale tree shake and update docusaurus add docusaurus ideal image plugin use svg and themed image delete unused static asset * move localized landing page * change GitLocalize project page * nit pick * remove ignore to have the block checked
89 lines
2.9 KiB
Plaintext
89 lines
2.9 KiB
Plaintext
---
|
|
title: "Custom Hooks"
|
|
description: "Defining your own Hooks "
|
|
---
|
|
|
|
## Defining custom Hooks
|
|
|
|
Component's stateful logic can be extracted into usable function by creating custom Hooks.
|
|
|
|
Consider that we have a component which subscribes to an agent and displays the messages sent to it.
|
|
```rust
|
|
use yew::{function_component, html, use_effect, use_state, Callback};
|
|
use yew_agent::Bridged;
|
|
// EventBus is an implementation yew_agent::Agent
|
|
use website_test::agents::EventBus;
|
|
|
|
|
|
#[function_component(ShowMessages)]
|
|
pub fn show_messages() -> Html {
|
|
let state = use_state(Vec::new);
|
|
|
|
{
|
|
let state = state.clone();
|
|
use_effect(move || {
|
|
let producer = EventBus::bridge(Callback::from(move |msg| {
|
|
let mut messages = (*state).clone();
|
|
messages.push(msg);
|
|
state.set(messages)
|
|
}));
|
|
|
|
|| drop(producer)
|
|
});
|
|
}
|
|
|
|
let output = state.iter().map(|it| html! { <p>{ it }</p> });
|
|
html! { <div>{ for output }</div> }
|
|
}
|
|
```
|
|
|
|
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 messages, instead of copying the code we can move the logic into a custom hook.
|
|
|
|
We'll start by creating a new function called `use_subscribe`.
|
|
The `use_` prefix conventionally denotes that a function is a hook.
|
|
This function will take no arguments and return `Rc<RefCell<Vec<String>>>`.
|
|
```rust
|
|
use std::{cell::RefCell, rc::Rc};
|
|
|
|
fn use_subscribe() -> Rc<RefCell<Vec<String>>> {
|
|
todo!()
|
|
}
|
|
```
|
|
|
|
This is a simple hook which can be created by combining other hooks. For this example, we'll two pre-defined hooks.
|
|
We'll use `use_state` hook to store the `Vec` for messages, so they persist between component re-renders.
|
|
We'll also use `use_effect` to subscribe to the `EventBus` `Agent` so the subscription can be tied to component's lifecycle.
|
|
|
|
```rust
|
|
use std::collections::HashSet;
|
|
use yew::{use_effect, use_state, Callback};
|
|
use yew_agent::Bridged;
|
|
// EventBus is an implementation yew_agent::Agent
|
|
use website_test::agents::EventBus;
|
|
|
|
fn use_subscribe() -> Vec<String> {
|
|
let state = use_state(Vec::new);
|
|
|
|
let effect_state = state.clone();
|
|
|
|
use_effect(move || {
|
|
let producer = EventBus::bridge(Callback::from(move |msg| {
|
|
let mut messages = (*effect_state).clone();
|
|
messages.push(msg);
|
|
effect_state.set(messages)
|
|
}));
|
|
|| drop(producer)
|
|
});
|
|
|
|
(*state).clone()
|
|
}
|
|
```
|
|
|
|
Although this approach works in almost all cases, it can't be used to write primitive hooks like the pre-defined hooks we've been using already
|
|
|
|
### Writing primitive hooks
|
|
|
|
`use_hook` function is used to write such hooks. View the docs on [docs.rs](https://docs.rs/yew/0.18.0/yew-functional/use_hook.html) for the documentation
|
|
and `hooks` directory to see implementations of pre-defined hooks.
|