# Why Choose Riverpod? - Accessing the Providers

> This post is based off a presentation I did at Devfest 2023 in Cape Town on 23 Nov 2023. [VIDEO](https://youtu.be/tUH4KD2GUgQ) | [PRESENTATION](https://www.canva.com/design/DAF0PW9xADM/rpt3TKfDU-waodWHH6DOvQ/view)

---

Previously we covered the extension methods provided by Riverpod, in this post we will take look at how we access these providers

---

### UI

Some of you. may have notice the two references to "ref" in the examples in the previous parts of this series, similar to build context, that is how Riverpod accesses its providers. On the UI side you will have a `WidgetRef` and within a Riverpod Provider you will simply use `Ref`.

For the UI side we simply need to replace the `StatelessWidget` with the `ConsumerWidget` which will then add the `WidgetRef` as the second argument on the widgets build method, from there we have access to many of the same accessors we would use with `Provider` or `BLoC`/`Cubit`. There is also a `StatefulConsumer` widget as well as Hook versions available in a separate package for those who make use of `flutter_hooks`.

```dart
// UI Side
class Widget extends ConsumerWidget {
    Widget build(BuildContext context, WidgetRef ref) {
      final read = ref.read(operationsProvider(task.id));
      
      final watch = ref.watch(operationsProvider(task.id));
      
      final select = ref.watch(
        operationsProvider(task.id)
          .select((v) => v.first
      );
      
      final (first, second) = ref.watch(
        operationsProvider(task.id).select(
          (v) => (v.first, v.second),
        ),
      );
    }
}
```

For those not familiar, we have the `read` which is used simply for accessing data from the provider, something which is advised against in the context of a widget as naturally any changes to the data will be ignored, so be careful when choosing to go this route and making sure the UI does not need to respond to changes.

`watch` is, as the name suggest, a listener on the state and will trigger a rebuild whenever any piece of data within that state updates allowing the UI to reflect any of those changes.

Along with the `watch` we also have the ability to use `select` which will allow us to scope which values within the state the listener responds to. This provides a lot more control over what triggers the widget to redraw which can be handy in larger states and help with performance.

### Classes

When it comes to accessing providers form within another provider, it is even more straightforward, here you would always be using `read` which is accessed from the `Ref` that is available within all Riverpod Providers.

```dart
class SharedNotifier extends StateNotifier<SharedState> {
  final Ref ref;
  final String id;

  SharedNotifier(this.ref, this.id) : super(SharedState.initial());
  
  Future<void> updateTaskStatus(TaskStatus status) async {
    ref.read(sampleNetworkProvider)
      ..updateFlows(state.task, true, type)
      ..updateFlowStatus(state.order, status, type);
  }
}
```

In the above code we are accessing one of our network providers and chaining a couple of methods onto that in order to fire off a set of API calls to update the status of the currently active task.

---

Next we will take a look at `ProviderScope` the Riverpod widget that gives us most of it super powers.

---

I hope you found this interesting, and if you have any questions, comments, or improvements, feel free to drop a comment. Enjoy your development journey :D

Thanks for reading.

---

* [What is Riverpod?](https://remelehane.dev/what-is-riverpod)
    
* [Riverpod Extensions](https://remelehane.dev/riverpod-extensions)
    
* [Accessing the Providers](https://remelehane.dev/accessing-the-providers)
    
* [ProviderScope](https://remelehane.dev/providerscope)
    
* [Testing](https://remelehane.dev/testing)
