Using Riverpod with Objects - always reinstantiate once property changes?
To trigger a state change you have to use the state
setter. The implementation looks like this:
@protected
set state(T value) {
assert(_debugIsMounted(), '');
final previousState = _state;
_state = value;
/// only notify listeners when should
if (!updateShouldNotify(previousState, value)) {
return;
}
_controller?.add(value);
// ...
The internal StreamController<T> _controller
needs to be triggered (add
), to notify listeners (in this case riverpod) about updates.
By using state.name = something
you're not informing the StateNotifier
about a new state (not calling the state setter). Only your object holds the new value but nobody was notified.
Your state is mutable and that very often leads to such misbehavior. By using an immutable object you can prevent such errors in the first place. Write it yourself or use freezed.
Learn more about immutability in my talk
Fellow7000
Updated on December 19, 2022Comments
-
Fellow7000 over 1 year
I am making first steps with Riverpod and just want to check if my understanding of handling changes of some data class properties using Riverpod is correct.
Imagine, I have a data class like that:
class MyClass { final String name; final int id; const MyClass(this.name, this.id); }
Then I create a StateNotifier:
class MyClassStateNotifier extends StateNotifier<MyClass> { MyClassStateNotifier(MyClass state) : super(state); void setName(String name) { state.name = name; } }
And this won't work - UI will not be rebuilt after calling setName this way.
So I need to modify classes in the following way:
class MyClass { final String name; final int id; const MyClass(this.name, this.id); MyClass copyWith({name, id}) { return MyClass(name ?? this.name, id ?? this.id); } }
and the StateNotifier as following:
class MyClassStateNotifier extends StateNotifier<MyClass> { MyClassStateNotifier(MyClass state) : super(state); void setName(String name) { state = state.copyWith(name: name); } }
This pair will work and the UI will be rebuilt.
So, my question: does one always need to reinstantiate the object in this way?..
From my perspective, this is a bit strange (simple datatypes like String / int do not require this) and the boilerplate for copyWith method might become pretty huge if I have a dozen of object's properties.
Is there any better solution available for Riverpod or is it the only one and correct?..
Thanks in advance! :)
-
Fellow7000 about 2 yearsDanke für die Rückmeldung! :) Thanks for your answer! I've watched your video, so as I far as I understood it, this would be the only way to use Riverpod, one should focus in immutability and use plaug-ins to autogenerate the boilerplate code. Am I correct?