I've been using Riverpod with StateNotifier to store my app's configurations / settings. It's easy and convenient as I can use methods to update the state's values. I can always use StateProvider but then I have updated the state directly, which is not convenient (for me) especially when I have a lot of setting parameters. Using StateNotifier also works perfectly. Well, until recently.. then I found out that updating a setting value not only updates the UI that listens to that value, but also updates other parts of the UI that don't listen to it, but listen to other setting values in the same state. I hope you get what I mean from the last sentence. To make it clear, let me show you a very simple demonstration. We'll make 2 switches: Switch A and Switch B. Switch A will build Box A, and build Box B. should not Switch B will build Box B, and build Box A. should not Let's code! You can put all the code below into 1 single dart file. ; ; { settingA; settingB; Settings({ .settingA = , .settingB = , }); Settings copy({ settingA, settingB, }) => Settings( settingA: settingA ?? .settingA, settingB: settingB ?? .settingB, ); } import 'package:flutter/material.dart' import 'package:flutter_riverpod/flutter_riverpod.dart' class Settings final bool final bool this false this false bool bool this this First, create the Settings class. The copy method will be used to update the State later. allSettingsProvider = StateNotifierProvider<SettingsNotifier>((ref) => SettingsNotifier()); { SettingsNotifier() : (Settings()); updateSettingA( settingA) { newState = state.copy(settingA: settingA); state = newState; } updateSettingB( settingB) { newState = state.copy(settingB: settingB); state = newState; } } final < > class SettingsNotifier extends StateNotifier Settings super void bool final void bool final Next, create the StateNotifier with 2 methods to update each Settings' values. You see here we use the copy method we created in the Settings class. { Widget build(BuildContext context) { MaterialApp( home: Scaffold( body: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Center(child: BuildBoxA()), Center(child: BuildBoxB()), ], ), ), ); } } { Widget build(BuildContext context, ScopedReader watch) { ( ); settingA = watch(allSettingsProvider.state).settingA; Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Switch.adaptive( value: settingA, onChanged: (value) { context.read(allSettingsProvider).updateSettingA(value); }, ), ], ); } } { Widget build(BuildContext context, ScopedReader watch) { ( ); settingB = watch(allSettingsProvider.state).settingB; Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Switch.adaptive( value: settingB, onChanged: (value) { context.read(allSettingsProvider).updateSettingB(value); }, ), ], ); } } class TestPage extends StatelessWidget @override return class BuildBoxA extends ConsumerWidget @override print 'Building Box A' final bool return class BuildBoxB extends ConsumerWidget @override print 'Building Box B' final bool return Next is the UI. Like I said, it's a very simple demo. No need to think about refactoring here. The result: Not good, right? Turning on and off Switch A should only build Box A, but it also builds Box B. Why? It's because we replace the whole state with a new one. Every value in Settings gets updated. Is there any way to update just a single value in the state? I couldn't find one. So I headed to Github and the nice people there pointed out that I don't need to worry about how I write to the state, but rather how I read it. There's an example in the official documentation . here So, let's make a few changes to the code. Add 2 Providers and change BuildBoxA and BuildBoxB like this: settingAProvider = Provider< >((ref) => ref.watch(allSettingsProvider.state).settingA); settingBProvider = Provider< >((ref) => ref.watch(allSettingsProvider.state).settingB); { Widget build(BuildContext context, ScopedReader watch) { ( ); settingA = watch(settingAProvider); Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Switch.adaptive( value: settingA, onChanged: (value) { context.read(allSettingsProvider).updateSettingA(value); }, ), ], ); } } { Widget build(BuildContext context, ScopedReader watch) { ( ); settingB = watch(settingBProvider); Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Switch.adaptive( value: settingB, onChanged: (value) { context.read(allSettingsProvider).updateSettingB(value); }, ), ], ); } } final bool final bool class BuildBoxA extends ConsumerWidget @override print 'Building Box A' final bool return class BuildBoxB extends ConsumerWidget @override print 'Building Box B' final bool return The result: Exactly what I (we) wanted!