Skip to content

Commit

Permalink
Pass hook dependencies as the first function argument (#2861)
Browse files Browse the repository at this point in the history
* Add use_effect_with

* Fix doc

* Add NeverEq

* Save as deps-and-runner

* remove with_deps

* fix other use_effect_with_deps

* add migration guide

* fix website

* fix doc test

* return use_effect_base

* fix docs

* fmt

* fix doc tests

* noeq

* use_callback

* finsihing touches

* fmt

* nighly fmt

* fix mistake

---------

Co-authored-by: Julius Lungys <32368314+voidpumpkin@users.noreply.github.com>
  • Loading branch information
arniu and voidpumpkin authored Apr 3, 2023
1 parent bdf5712 commit 6f4cdf2
Show file tree
Hide file tree
Showing 33 changed files with 299 additions and 315 deletions.
63 changes: 30 additions & 33 deletions examples/function_memory_game/src/components/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,36 @@ pub fn App() -> Html {
let flip_back_timer: Rc<RefCell<Option<Timeout>>> = use_mut_ref(|| None);
let sec_past_time = *sec_past;

use_effect_with_deps(
move |state| {
// game reset
if state.status == Status::Ready {
sec_past.set(0);
}
// game start
else if *sec_past == 0 && state.last_card.is_some() {
let sec_past = sec_past.clone();
let mut sec = *sec_past;
*sec_past_timer.borrow_mut() = Some(Interval::new(1000, move || {
sec += 1;
sec_past.set(sec);
}));
}
// game over
else if state.status == Status::Passed {
*sec_past_timer.borrow_mut() = None;
*flip_back_timer.borrow_mut() = None;
state.dispatch(Action::TrySaveBestScore(*sec_past));
}
// match failed
else if state.rollback_cards.is_some() {
let cloned_state = state.clone();
let cloned_rollback_cards = state.rollback_cards.clone().unwrap();
*flip_back_timer.borrow_mut() = Some(Timeout::new(1000, move || {
cloned_state.dispatch(Action::RollbackCards(cloned_rollback_cards));
}));
}
|| ()
},
state.clone(),
);
use_effect_with(state.clone(), move |state| {
// game reset
if state.status == Status::Ready {
sec_past.set(0);
}
// game start
else if *sec_past == 0 && state.last_card.is_some() {
let sec_past = sec_past.clone();
let mut sec = *sec_past;
*sec_past_timer.borrow_mut() = Some(Interval::new(1000, move || {
sec += 1;
sec_past.set(sec);
}));
}
// game over
else if state.status == Status::Passed {
*sec_past_timer.borrow_mut() = None;
*flip_back_timer.borrow_mut() = None;
state.dispatch(Action::TrySaveBestScore(*sec_past));
}
// match failed
else if state.rollback_cards.is_some() {
let cloned_state = state.clone();
let cloned_rollback_cards = state.rollback_cards.clone().unwrap();
*flip_back_timer.borrow_mut() = Some(Timeout::new(1000, move || {
cloned_state.dispatch(Action::RollbackCards(cloned_rollback_cards));
}));
}
|| ()
});

let on_reset = {
let state = state.clone();
Expand Down
11 changes: 4 additions & 7 deletions examples/function_router/src/components/author_card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,11 @@ pub fn AuthorCard(props: &Props) -> Html {

{
let author_dispatcher = author.dispatcher();
use_effect_with_deps(
move |seed| {
author_dispatcher.dispatch(*seed);
use_effect_with(seed, move |seed| {
author_dispatcher.dispatch(*seed);

|| {}
},
seed,
);
|| {}
});
}

let author = &author.inner;
Expand Down
11 changes: 4 additions & 7 deletions examples/function_router/src/components/post_card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,11 @@ pub fn PostCard(props: &Props) -> Html {

{
let post_dispatcher = post.dispatcher();
use_effect_with_deps(
move |seed| {
post_dispatcher.dispatch(*seed);
use_effect_with(seed, move |seed| {
post_dispatcher.dispatch(*seed);

|| {}
},
seed,
);
|| {}
});
}

let post = &post.inner;
Expand Down
28 changes: 11 additions & 17 deletions examples/function_router/src/components/progress_delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,22 @@ pub fn ProgressDelay(props: &Props) -> Html {

{
let value = value.clone();
use_effect_with_deps(
move |_| {
let interval = (duration_ms / RESOLUTION).min(MIN_INTERVAL_MS);
let interval = Interval::new(interval, move || value.dispatch(ValueAction::Tick));
use_effect_with((), move |_| {
let interval = (duration_ms / RESOLUTION).min(MIN_INTERVAL_MS);
let interval = Interval::new(interval, move || value.dispatch(ValueAction::Tick));

|| {
let _interval = interval;
}
},
(),
);
|| {
let _interval = interval;
}
});
}

{
let value = value.clone();
use_effect_with_deps(
move |props| {
value.dispatch(ValueAction::Props(props.clone()));
|| {}
},
props.clone(),
);
use_effect_with(props.clone(), move |props| {
value.dispatch(ValueAction::Props(props.clone()));
|| {}
});
}

let value = &value.value;
Expand Down
11 changes: 4 additions & 7 deletions examples/function_router/src/pages/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@ pub fn Author(props: &Props) -> Html {

{
let author_dispatcher = author.dispatcher();
use_effect_with_deps(
move |seed| {
author_dispatcher.dispatch(*seed);
use_effect_with(seed, move |seed| {
author_dispatcher.dispatch(*seed);

|| {}
},
seed,
);
|| {}
});
}

let author = &author.inner;
Expand Down
13 changes: 5 additions & 8 deletions examples/function_router/src/pages/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,11 @@ pub fn Post(props: &Props) -> Html {

{
let post_dispatcher = post.dispatcher();
use_effect_with_deps(
move |seed| {
post_dispatcher.dispatch(*seed);

|| {}
},
seed,
);
use_effect_with(seed, move |seed| {
post_dispatcher.dispatch(*seed);

|| {}
});
}

let post = &post.inner;
Expand Down
11 changes: 4 additions & 7 deletions examples/function_todomvc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ fn app() -> Html {
});

// Effect
use_effect_with_deps(
move |state| {
LocalStorage::set(KEY, &state.clone().entries).expect("failed to set");
|| ()
},
state.clone(),
);
use_effect_with(state.clone(), move |state| {
LocalStorage::set(KEY, &state.clone().entries).expect("failed to set");
|| ()
});

// Callbacks
let onremove = {
Expand Down
2 changes: 1 addition & 1 deletion examples/js_callback/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ static WASM_BINDGEN_SNIPPETS_PATH: OnceCell<String> = OnceCell::new();

#[function_component]
fn Important() -> Html {
let msg = use_memo(|_| bindings::hello(), ());
let msg = use_memo((), |_| bindings::hello());
html! {
<>
<h2>{"Important"}</h2>
Expand Down
35 changes: 16 additions & 19 deletions packages/yew-router/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,26 +84,23 @@ fn base_router(props: &RouterProps) -> Html {
{
let loc_ctx_dispatcher = loc_ctx.dispatcher();

use_effect_with_deps(
move |history| {
use_effect_with(history, move |history| {
let history = history.clone();
// Force location update when history changes.
loc_ctx_dispatcher.dispatch(history.location());

let history_cb = {
let history = history.clone();
// Force location update when history changes.
loc_ctx_dispatcher.dispatch(history.location());

let history_cb = {
let history = history.clone();
move || loc_ctx_dispatcher.dispatch(history.location())
};

let listener = history.listen(history_cb);

// We hold the listener in the destructor.
move || {
std::mem::drop(listener);
}
},
history,
);
move || loc_ctx_dispatcher.dispatch(history.location())
};

let listener = history.listen(history_cb);

// We hold the listener in the destructor.
move || {
std::mem::drop(listener);
}
});
}

html! {
Expand Down
31 changes: 11 additions & 20 deletions packages/yew/src/functional/hooks/use_callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,13 @@ use crate::functional::{hook, use_memo};
/// };
///
/// // This callback depends on (), so it's created only once, then MyComponent
/// // will be rendered only once even when you click the button mutiple times.
/// let callback = use_callback(move |name, _| format!("Hello, {}!", name), ());
/// // will be rendered only once even when you click the button multiple times.
/// let callback = use_callback((), move |name, _| format!("Hello, {}!", name));
///
/// // It can also be used for events, this callback depends on `counter`.
/// let oncallback = {
/// let counter = counter.clone();
/// use_callback(
/// move |_e, counter| {
/// let _ = **counter;
/// },
/// counter,
/// )
/// };
/// let oncallback = use_callback(counter.clone(), move |_e, counter| {
/// let _ = **counter;
/// });
///
/// html! {
/// <div>
Expand All @@ -66,7 +60,7 @@ use crate::functional::{hook, use_memo};
/// }
/// ```
#[hook]
pub fn use_callback<IN, OUT, F, D>(f: F, deps: D) -> Callback<IN, OUT>
pub fn use_callback<IN, OUT, F, D>(deps: D, f: F) -> Callback<IN, OUT>
where
IN: 'static,
OUT: 'static,
Expand All @@ -75,13 +69,10 @@ where
{
let deps = Rc::new(deps);

(*use_memo(
move |deps| {
let deps = deps.clone();
let f = move |value: IN| f(value, deps.as_ref());
Callback::from(f)
},
deps,
))
(*use_memo(deps, move |deps| {
let deps = deps.clone();
let f = move |value: IN| f(value, deps.as_ref());
Callback::from(f)
}))
.clone()
}
Loading

0 comments on commit 6f4cdf2

Please sign in to comment.