Reliable use_reducer dispatch and use_state setter#2126
Merged
Conversation
|
Visit the preview URL for this PR (updated for commit f800148): https://yew-rs--pr2126-stale-value-ptcefc0e.web.app (expires Thu, 18 Nov 2021 11:28:23 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 |
Member
Author
|
Old Approach: struct CounterState {
counter: i32,
}
let counter = use_reducer_with_init(
|prev: std::rc::Rc<CounterState>, action: i32| CounterState {
counter: prev.counter + action,
},
0,
|initial: i32| CounterState {
counter: initial + 10,
},
);New Approach: struct CounterState {
counter: i32,
}
impl Default for CounterState {
fn default() -> Self {
Self { counter: 10 }
}
}
impl Reducible for CounterState {
type Action = i32;
fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
Self {
counter: self.counter + action,
}
.into()
}
}
let counter = use_reducer(CounterState::default); |
siku2
reviewed
Nov 11, 2021
Member
siku2
left a comment
There was a problem hiding this comment.
Just some documentation grammar
Co-authored-by: Simon <simon@siku2.io>
Co-authored-by: Simon <simon@siku2.io>
Co-authored-by: Simon <simon@siku2.io>
voidpumpkin
approved these changes
Nov 11, 2021
siku2
approved these changes
Nov 11, 2021
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
As described in #2112,
use_state's value is susceptible to outdated values and causes theset_if_neqto be unreliable.The reducer function is also susceptible to the same problem as it is tied to the dispatch function with the current implementation.
The value going stale problem mostly can be solved by adapting established patterns from the React world but it still requires the setter and dispatch function to work reliably (Or functions like their counterpart in React).
This PR takes a different approach which makes the reducer function to be static to avoid it becoming stale or attempting to pass a different reducer function between renders.
(Defining the reducer function outside of the component is a common practice in React and attempting to update another state while the component is rendering will result in an error in React.)
This PR consists of the following change:
use_reducernow accepts 1 argument which is an initialiser function.use_reducernow requires to implementReducibletrait which providesActionandreduce.use_reducer_eqwhich only re-renders ifprev_state != next_state.use_stateis implemented withuse_reducer.use_state_eqwhich only re-renders ifprev_state != next_state(Implemented withuse_reducer_eq).UseStateHandleandUseReducerHandleonly implementsPartialEqifT: PartialEq.dispatcherandsettermethod. It always implementsPartialEqeven ifT: !PartialEq. This can be passed as a prop / context if T is notPartialEq.Fixes #2112 (in conjunction with #2125).
Checklist
cargo make pr-flow