Comments (1)
I think the question boils down to "how can I use iternally mutable data with Reducible
". I'll try to answer this, but first I want to clarify why the behaviour of Implementation 2 is expected.
First of all, use_reducer
always leads to a re-render when you dispatch an action to it, no matter what the implementation of Reducible
does. This is what you experience by the context providing component always re-rendering. The difference between the two examples is how the ContextProvider
handles the value in its context
; to decide whether to re-render any subscribed children, it compares the old to the new value when it itself re-renders. This means we should look at the PartialEq
for state: UseReducerHandle<_>
, which simply forwards to <StateData as PartialEq>::eq
. But here lies the problem: if you use only interior mutability in the reducer, then the old value will have been also updated, and the comparison is a trivially true by reflexivity! So the context provider concludes that it doesn't need to re-render its children.
So how to fix it? The simplest, but perhaps too lazy of an approach, would be to wrap the context value in a struct that simply always returns false from its PartialEq
. This way, the ContextProvider
will always re-render children consumers, whenever it itself re-renders.
struct ChatroomContext(UseReducerHandle<StateData>);
impl PartialEq for ChatroomContext {
fn eq(&self, other: &Self) { false }
}
...
<ContextProvider<ChatroomContext> context={ChatroomContext(state)} >
...
In case this is too coarse and leads to too many unnecessary re-renders, you should introduce some sort of generational counter into the state that lives outside the shared mutable state that counts which "version" the state represents:
pub struct SharedState {
pub open: bool, // etc..
}
#[derive(Clone)]
pub struct StateData {
generation: u32,
pub state: Rc<RefCell<SharedState>>,
}
impl PartialEq for StateData {
fn eq(&self, other: &Self) -> bool {
// this assumes that there is only one history for each state, which is true in use_reducer
Rc::ptr_eq(&self.state, &other.state) && self.generation == other.generation
}
}
impl StateData {
// small helper method to facilitate incrementing the generation counter
fn mutate<'a>(self: &'a mut Rc<Self>) -> impl 'a + DerefMut<Target = SharedState> {
// We can cheaply clone ourself. With some further work you can write this without
// leaking the `Clone` impl for StateData
let this = Rc::make_mut(self);
// Since we are borrowing mutably, we assume that the data "changed" and we increase the generation
this.generation += 1;
this.state.borrow_mut()
}
}
impl Reducible for StateData {
type Action = StateAction;
fn reduce(mut self: Rc<Self>, action: Self::Action) -> Rc<Self> {
match action {
StateAction::SetPreviewOpen(x) => {
let mut state = StateData::mutate(&mut self);
state.open = x;
}
}
self
}
}
....
// This context provider will see the same shared state, but different generation numbers
// On subsequent re-renders, it will trigger re-renders of downstream when the generation changed
<ContextProvider<ChatroomContext> context={state} >
....
from yew.
Related Issues (20)
- Tutorial proxy-backend returning `index.html` not json? HOT 6
- use_effect lacks documentation HOT 2
- Tutorial uses String not AttrValue
- File based Routing HOT 1
- Caution about navigator callbacks in functional components is confusing
- Yew Agent documentation
- When passing `Classes` in `html!`, component props don't need `.clone()`, but element props do HOT 1
- [Feature]: Provide a `Default` trait implementation for the `UseStateHandle` struct HOT 2
- Japanese documents are out of date HOT 1
- Why not provide some Form components? HOT 1
- SSR + hydration results in a stalled request
- I am unable to build even the simplest Yew applications using Rust 1.76 and running under macOS 14.3 HOT 1
- Blob download encoding
- `VRaw` namespace support for `svg` contents.
- Issue with change detection? HOT 4
- Port issue HOT 1
- implicit_clone does not play nice with indexmap 2.26 HOT 4
- the trait bound `implicit_clone::unsync::IMap<_, _>: From<indexmap::IndexMap<K, V>>` is not satisfied HOT 4
- Tutorial error about fetching data
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from yew.