Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jetli/yew-hooks
Hooks for Yew, inspired by streamich/react-use and alibaba/hooks.
https://github.com/jetli/yew-hooks
hooks react react-hooks rust wasm webassembly yew yew-hooks
Last synced: 3 months ago
JSON representation
Hooks for Yew, inspired by streamich/react-use and alibaba/hooks.
- Host: GitHub
- URL: https://github.com/jetli/yew-hooks
- Owner: jetli
- License: apache-2.0
- Created: 2021-12-23T02:35:18.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-04-03T16:57:15.000Z (7 months ago)
- Last Synced: 2024-05-10T08:22:15.825Z (6 months ago)
- Topics: hooks, react, react-hooks, rust, wasm, webassembly, yew, yew-hooks
- Language: Rust
- Homepage: https://jetli.github.io/yew-hooks/
- Size: 28.7 MB
- Stars: 158
- Watchers: 2
- Forks: 13
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
- awesome-yew - yew-hooks - Custom Hooks library for Yew, inspired by [streamich/react-use](https://github.com/streamich/react-use) and [alibaba/hooks](https://github.com/alibaba/hooks). (Crates / Hooks)
README
Yew Hooks
Hooks for [Yew](https://github.com/yewstack/yew), inspired by [streamich/react-use](https://github.com/streamich/react-use), [alibaba/hooks](https://github.com/alibaba/hooks) and [vueuse/vueuse](https://github.com/vueuse/vueuse).
```rust
use yew_hooks::prelude::*;#[function_component(Counter)]
fn counter() -> Html {
let counter = use_counter(0);let onincrease = {
let counter = counter.clone();
Callback::from(move |_| counter.increase())
};
let ondecrease = {
let counter = counter.clone();
Callback::from(move |_| counter.decrease())
};html! {
<>
{ "Increase" }
{ "Decrease" }
{ "Current value: " }
{ *counter }
>
}
}
```## Hooks
### State
- `use_toggle` - tracks state of counterparts.
- `use_bool_toggle` - tracks state of a boolean.
- `use_counter` - tracks state of a number.
- `use_latest` - returns the latest immutable ref to state or props.
- `use_mut_latest` - returns the latest mutable ref to state or props.
- `use_previous` - returns the previous immutable ref to state or props.
- `use_list` - tracks state of a list.
- `use_map` - tracks state of a hash map.
- `use_set` - tracks state of a hash set.
- `use_queue` - tracks state of a queue.
- `use_raf_state` - creates `set` method which only updates after `requestAnimationFrame`.
- `use_state_ptr_eq` - similar to `use_state_eq`, but checks if the two `Rc`s of values point to the same allocation.
- `use_renders_count` - counts component renders.
- `use_default` - returns the default value when state is None.
- `use_debounce_state` - debounces state.
- `use_throttle_state` - throttles state.### Side-effects
- `use_async` - resolves an `async` future, e.g. fetching REST api.
- `use_websocket` - communicates with `WebSocket`.
- `use_title` - sets title of the page.
- `use_favicon` - sets favicon of the page.
- `use_local_storage` - manages a value in `localStorage`.
- `use_session_storage` - manages a value in `sessionStorage`.
- `use_before_unload` - shows browser alert when user try to reload or close the page.
- `use_debounce` - debounces a function.
- `use_debounce_effect` - debounces an effect.
- `use_throttle` - throttles a function.
- `use_throttle_effect` - throttles an effect.
- `use_clipboard` - reads from or writes to clipboard for text/bytes.### Lifecycles
- `use_effect_once` - a modified use_effect hook that only runs once.
- `use_effect_update` - runs an effect only on updates.
- `use_mount` - calls mount callbacks.
- `use_unmount` - calls unmount callbacks.
- `use_is_first_mount` - checks if current render is first.
- `use_is_mounted` - tracks if component is mounted.
- `use_event` - subscribes to events.
- `use_logger` - logs in console as component goes through life cycles.### Animations
- `use_timeout` - schedules a timeout to invoke callback.
- `use_interval` - schedules an interval to invoke callback.
- `use_update` - returns a callback, which re-renders component when called.
- `use_raf` - re-renders component on each `requestAnimationFrame`.### Sensors
- `use_window_size` - tracks Window dimensions.
- `use_window_scroll` - tracks Window scroll position.
- `use_scroll` - tracks an HTML element's scroll position.
- `use_scrolling` - tracks whether HTML element is scrolling.
- `use_infinite_scroll` - infinite scrolling of the element.
- `use_location` - tracks brower's location value.
- `use_hash` - tracks brower's location hash value.
- `use_search_param` - tracks brower's location search param value.
- `use_size` - tracks an HTML element's dimensions using the `ResizeObserver` API.
- `use_measure` - tracks an HTML element's dimensions using the `ResizeObserver` API.
- `use_geolocation` - tracks user's geographic location.
- `use_swipe` - detects swipe based on TouchEvent.
- `use_visible` - checks if an element is visible.### UI
- `use_click_away` - triggers a callback when user clicks outside the target element.
- `use_drag` - tracks file, link and copy-paste drags, used along with `use_drop` hook.
- `use_drop` - tracks file, link and copy-paste drops.
- `use_media` - plays video or audio and exposes its controls.## Examples
### `use_counter` demo
```rust
use yew::prelude::*;
use yew_hooks::prelude::*;#[function_component(Counter)]
fn counter() -> Html {
let counter = use_counter(0);let onincrease = {
let counter = counter.clone();
Callback::from(move |_| counter.increase())
};
let ondecrease = {
let counter = counter.clone();
Callback::from(move |_| counter.decrease())
};
let onincreaseby = {
let counter = counter.clone();
Callback::from(move |_| counter.increase_by(10))
};
let ondecreaseby = {
let counter = counter.clone();
Callback::from(move |_| counter.decrease_by(10))
};
let onset = {
let counter = counter.clone();
Callback::from(move |_| counter.set(100))
};
let onreset = {
let counter = counter.clone();
Callback::from(move |_| counter.reset())
};html! {
{ "Increase" }
{ "Decrease" }
{ "Increase by 10" }
{ "Decrease by 10" }
{ "Set to 100" }
{ "Reset" }
{ "Current value: " }
{ *counter }
}
}
```### `use_async` demo
```rust
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use yew::prelude::*;
use yew_hooks::prelude::*;#[function_component(UseAsync)]
pub fn async_demo() -> Html {
let state = use_async(async move { fetch_repo("jetli/yew-hooks".to_string()).await });let onclick = {
let state = state.clone();
Callback::from(move |_| {
// You can trigger to run in callback or use_effect.
state.run();
})
};html! {
{ "Start to load repo: jetli/yew-hooks" }
{
if state.loading {
html! { "Loading, wait a sec..." }
} else {
html! {}
}
}
{
if let Some(repo) = &state.data {
html! {
<>
{ "Repo name: " }{ &repo.name }
{ "Repo full name: " }{ &repo.full_name }
{ "Repo description: " }{ &repo.description }
{ "Owner name: " }{ &repo.owner.login }
{ "Owner avatar: " }
>
}
} else {
html! {}
}
}
{
if let Some(error) = &state.error {
match error {
Error::DeserializeError => html! { "DeserializeError" },
Error::RequestError => html! { "RequestError" },
}
} else {
html! {}
}
}
}
}async fn fetch_repo(repo: String) -> Result {
fetch::(format!("https://api.github.com/repos/{}", repo)).await
}/// You can use reqwest or other crates to fetch your api.
async fn fetch(url: String) -> Result
where
T: DeserializeOwned,
{
let response = reqwest::get(url).await;
if let Ok(data) = response {
if let Ok(repo) = data.json::().await {
Ok(repo)
} else {
Err(Error::DeserializeError)
}
} else {
Err(Error::RequestError)
}
}#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
struct User {
id: i32,
login: String,
avatar_url: String,
}#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
struct Repo {
id: i32,
name: String,
full_name: String,
description: String,
owner: User,
}// You can use thiserror to define your errors.
#[derive(Clone, Debug, PartialEq)]
enum Error {
RequestError,
DeserializeError,
// etc.
}
```### `use_websocket` demo
```rust
use yew::prelude::*;
use yew_hooks::prelude::*;#[function_component(UseWebSocket)]
pub fn web_socket() -> Html {
let history = use_list(vec![]);
let ws = use_websocket("wss://echo.websocket.events/".to_string());let onclick = {
let ws = ws.clone();
let history = history.clone();
Callback::from(move |_| {
let message = "Hello, world!".to_string();
ws.send(message.clone());
history.push(format!("[send]: {}", message));
})
};{
let history = history.clone();
let ws = ws.clone();
use_effect_with(
ws.message,
move |message| {
if let Some(message) = &**message {
history.push(format!("[recv]: {}", message.clone()));
}
|| ()
},
);
}html! {
{ "Send" }
{ "Message history: " }
{
for history.current().iter().map(|message| {
html! {
{ message }
}
})
}
}
}
```## Demo
[Check out a live demo](https://jetli.github.io/yew-hooks/)
## Contribute
Feel free to take a look at the current issues in this repo for anything that currently needs to be worked on.
You are also welcome to open a PR or a new issue if you see something is missing or could be improved upon.
## License
Apache-2.0/MIT