패키지, 저장소 및 앱 카테고리 검색

패키지 상세v0.3.0

riverpod_context

이 패키지는 riverpod에 대해 context.read 및 context.watch를 다시 제공합니다

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
345
좋아요
18
Pub 점수
150

패키지 설치

flutter pub add riverpod_context

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

riverpod_context 패키지는 최신 버전에서 제거된 편리한 context.read 및 context.watch 메서드를 Riverpod에 복원합니다. 이는 개발자가 ProviderContainer나 기타 대안을 사용하지 않고도 BuildContext에서 직접 제공자를 액세스할 수 있게 해줍니다. 이는 여러 플랫폼에서 Riverpod의 상태 관리 시스템을 사용할 때 코드 가독성과 개발자 경험을 향상시킵니다.

사용 사례

  • 위젯 내에서 공급자에 액세스하기
  • UI에서 상태 사용을 단순화하기
  • 복잡한 위젯 트리에서 코드 명확성 향상
  • ProviderContainer 컨텍스트가 아닌 곳에서 watch 및 read 패턴 활성화
  • Riverpod 사용 시 부가 코드 줄이기

주요 기능

  • context.read() 다시 도입
  • context.watch() 재도입
  • 모든 Riverpod 제공자와 호환됩니다
  • 모든 주요 플랫폼을 지원합니다
  • 최소한의 설정 필요

적합한 대상

  • Riverpod를 사용하는 개발자들이 context.read/watch를 그리워함
  • 클린하고 읽기 쉬운 상태 접근을 필요로 하는 프로젝트
  • 개발자 사용성에 중점을 둔 팀
  • 다중 플랫폼을 대상으로 하는 앱
  • 중요한 상태 관리 사용을 하는 Flutter 앱

고려 사항

  • 성능 문제를 피하기 위해 신중한 사용이 필요합니다
  • 직접 ProviderContainer를 사용하는 경우 필요하지 않습니다
  • 향후 Riverpod 업데이트와 충돌할 수 있습니다
  • 적절한 공급자 스코프와 함께 사용하는 것이 가장 좋습니다
  • 깊이 중첩되거나 자주 재구성되는 위젯에서 피하십시오

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

This package brings back the context extensions for riverpod that were discontinued in version 1.0.0.

  • To read any provider, do context.read(myProvider)
  • To watch any provider, do context.watch(myProvider)

This package is meant to be used alongside riverpod and offers an alternative to the official ConsumerWidget and ConsumerStatefulWidget.

Getting Started

This assumes you already have flutter_riverpod (or hooks_riverpod) set up.

First, add riverpod_context as a dependency.

flutter pub add riverpod_context

Next, add InheritedConsumer underneath the root ProviderScope:

// Before
ProviderScope(
  child: MyApp(),
)
// After
ProviderScope(
  child: InheritedConsumer(
    child: MyApp(),
  ),
)

That's all.

Context Extensions

riverpod_context provides four convenient context extensions to interact with your providers.

context.read

context.read can be used anywhere without any special consideration. It naturally supports any providers, provider families as well as the new .select() syntax.

Widget build(BuildContext context) {
  // this won't rebuild based on 'myValue'
  String myValue = context.read(myProvider);
  return Text(myValue);
}
context.watch

context.watch watches the provider and triggers a rebuild of the given context when the providers state changes. It again supports any providers, provider families as well as the new .select() syntax.

Widget build(BuildContext context) {
  // this will rebuild each time 'myValue' changes
  String myValue = context.watch(myProvider);
  return Text(myValue);
}

🚨 There are a few important considerations to make when using context.watch. With those, you can also safely use any .autoDispose providers.

1. Only use inside build()

context.watch can only be used inside the build() method of a widget. Especially interaction callbacks (like onPressed) and StatefulWidgets initState, didChangeDependencies and other lifecycle handlers are not allowed.

2. Be cautious when conditionally watching providers

It is possible to conditionally watch providers. This is the case when context.watch may not be called on every rebuild.

Widget build(BuildContext context) {
  if (myCondition) {
    return Text(context.watch(myProvider));
  } else {
    return Container();
  }
}

In this example, when myCondition is false, context.watch is not called. This leads to an issue where the dependencies of the provider are not clearly defined.

It is important to make sure that this does not happen, since it can lead to leaking memory and wrong behavior!

Preventing this is however pretty simple.

If there exists another context.watch on the same context, this issue is resolved. Generally speaking, it requires at least one context.watch call on every build to be safe.

If in the example above, the myCondition actually comes from another context.watch call, you are safe.

Widget build(BuildContext context) {
  if (context.watch(myConditionProvider)) {
    // don't worry about this being called conditionally, 
    // we already have called context.watch once before
    return Text(context.watch(myProvider));
  } else {
    return Container();
  }
}

If not, use context.prime().

3. Or use context.prime() when conditionally watching providers

If context.watch is - under certain conditions - not called on every rebuild, you have to "prime" the context for the missing provider. This can be done using a simple context.prime() call.

In the previous example, this can be placed either in the else, or unconditionally at the top. It also has no effect to do it multiple times.

Widget build(BuildContext context) {
  context.prime(); // option 1: always prime
  if (myCondition) {
    return Text(context.watch(myProvider));
  } else {
    context.prime(); // option 2: prime to account for missing context.watch call
    return Container();
  }
}

As a rule just remember this:

Wherever you use context.watch conditionally, make sure to either have another unconditional context.watch or use context.prime on the same context.

Or in other words:

You are safe if on each rebuild there always is at least one call to either context.watch or context.prime.

context.refresh

context.refresh refreshes any provider.

Widget build(BuildContext context) {
  return TextButton(
    onPressed: () {
      context.refresh(myProvider);
    },
    child: const Text('Refresh'),
  );
}
context.invalidate

context.invalidate invalidates any provider.

Widget build(BuildContext context) {
  return TextButton(
    onPressed: () {
      context.invalidate(myProvider);
    },
    child: const Text('Invalidate'),
  );
}
context.listen

context.listen Listens to a provider without triggering a rebuild. This can be used inside the build() method or in the didChangeDependencies() of a stateful widget.

Widget build(BuildContext context) {
  
  context.listen(myProvider, (previous, value) {
    // do something
  });
  
  return SomeWidget();
}
Idempotent listeners

There will only ever be a single active listener for a specific context, meaning that calling context.listen multiple times for the same provider will only have the last listener active. Only because of this it is safe to use context.listen inside the build() method across rebuilds.

You can set fireImmediate: true to immediately fire the listener once. This will be ignored when re-listening to a provider, i.e. after a rebuild.

Widget build(BuildContext context) {

  // across multiple rebuilds, there will only exist a single listener on this provider
  // only on the first build, the listener will fire immediately
  context.listen(myProvider, (previous, value) {
    // do something
  }, fireImmediately: true);
  
  return SomeWidget();
}
Closing listeners

All listeners will only be closed when the context is disposed. Therefore it has no effect to call context.listen conditionally, especially with .autoDispose providers.

There are two ways to control the closing of a listener:

  • By using context.unlisten you can close the active listener on a provider.
  • When wanting more control over a listener, use context.subscribe.
Widget build(BuildContext context) {

  if (myCondition) {
    context.listen(myProvider, (previous, value) {
      // do something
    });
  } else {
    // this will remove the active listener on this provider
    // and properly dispose an .autoDispose provider
    context.unlisten(myProvider);
  }
  
  return SomeWidget();
}
context.subscribe

context.subscribe listens to a provider and returns the ProviderSubscription. Use this when you need to manually manage the subscription of a provider.

  • This can be used wherever you have a BuildContext, even in the initState() method.
  • Make sure to call subscription.close() when the listener is no longer needed.
class MyWidgetState extends State<MyWidget> {
  
  late ProviderSubscription subscription;
  
  @override
  void initState() {
    // store the returned subscription in a variable
    subscription = context.subscribe(myProvider, (previous, value) {
      // do something
    });
  }
  
  // ...
  
  @override dispose() {
    // make sure to properly close the subscription
    subscription.close();
  }
}

카테고리

의존성

의존성 목록 1 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.