I've been using what I found out was an anti-pattern when using Riverpod as my state management tool. I did what the user who asked this question did: update the properties that you want to change and add state = state. This solution worked up until the state_provider package was updated beyond 0.7.0, after which this solution stopped working altogether.
I've been trying the solution used in the thread below, but this will also not rebuild the UI for me. Can anyone tell me what I'm doing wrong here? I feel like the solution below should work, as this is essentially what you do with basically any other state management package, such as Redux.
My state model, Notifier and Provider
import 'package:hooks_riverpod/hooks_riverpod.dart';
class Test {
Test({this.prop1, this.prop2});
String? prop1;
int? prop2;
}
class TestNotifier extends StateNotifier<Test> {
TestNotifier() : super(Test());
void update() {
state.prop2 ??= 0;
state = state..prop2 = state.prop2! 1;
}
}
final StateNotifierProvider<TestNotifier, Test> testProvider =
StateNotifierProvider((ref) => TestNotifier());
Full main.dart file
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:practice_buddy/state/test_state.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends HookConsumerWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context, WidgetRef ref) {
final _testProvider = ref.watch(testProvider);
final _testNotifier = ref.watch(testProvider.notifier);
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'${_testProvider.prop2 ?? 0}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => _testNotifier.update(),
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Pubspec to show package versions
dependencies:
cloud_firestore: ^3.1.7
firebase_auth: ^3.3.6
firebase_core: ^1.12.0
flutter:
sdk: flutter
flutter_hooks: ^0.18.2
hooks_riverpod: ^1.0.3
My Flutter version is 2.8.1.
CodePudding user response:
This can be solved by passing a new instance on update.
void update() {
state.prop2 ??= 0;
state = state.copyWith(prop2: state.prop2! 1);
}
And on model class copyWith constructor.
Test copyWith({
String? prop1,
int? prop2,
}) {
return Test(
prop1: prop1 ?? this.prop1,
prop2: prop2 ?? this.prop2,
);
}
