Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[riverpod 3] NotifierProvider doesn't work with a NotifierBase mixin. #3546

Open
MiniSuperDev opened this issue May 14, 2024 · 0 comments
Open
Assignees
Labels
bug Something isn't working needs triage

Comments

@MiniSuperDev
Copy link

MiniSuperDev commented May 14, 2024

Hello, I'm using the version 3 from the dev branch

I want to create a mixin that works on provider and family provider. Which is possible with NotifierBase.

Now I want to create a widget that works with that mixin, I tried with NotifierProvider but it doesn't work.

On the other hand, if I use $Notifier as the mixin, and $NotifierProvider it works perfectly, but those classes will be not used like this as the docs said:

An implementation detail of `riverpod_generator`. Do not use.`
Working version with $Notifier and $NotifierProvider
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'main.g.dart';

mixin CounterMixin on $Notifier<int> {
  void increment() {
    state++;
  }
}

@riverpod
class CounterFamily extends _$CounterFamily with CounterMixin {
  @override
  int build({
    required int id,
  }) {
    return 0;
  }
}

@riverpod
class Counter extends _$Counter with CounterMixin {
  @override
  int build() {
    return 0;
  }
}

class CounterWidget extends ConsumerWidget {
  const CounterWidget({
    super.key,
    required this.title,
    required this.provider,
  });
  final String title;
  final $NotifierProvider<CounterMixin, int> provider;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Expanded(
      child: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(title),
              Text('${ref.watch(provider)}'),
              ElevatedButton(
                onPressed: () => ref.read(provider.notifier).increment(),
                child: const Text('increment'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

void main() {
  runApp(
    const ProviderScope(child: MyApp()),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Row(
        children: [
          const CounterWidget(
            title: 'counter',
            provider: counterProvider,
          ),
          CounterWidget(
            title: 'counterFamily 1',
            provider: counterFamilyProvider(id: 1),
          ),
          CounterWidget(
            title: 'counterFamily 2',
            provider: counterFamilyProvider(id: 2),
          ),
        ],
      ),
    );
  }
}
Not working version with NotifierBase and NotifierProvider
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'main.g.dart';

mixin CounterMixin on NotifierBase<int, int> {
  void increment() {
    state++;
  }
}

@riverpod
class CounterFamily extends _$CounterFamily with CounterMixin {
  @override
  int build({
    required int id,
  }) {
    return 0;
  }
}

@riverpod
class Counter extends _$Counter with CounterMixin {
  @override
  int build() {
    return 0;
  }
}

class CounterWidget extends ConsumerWidget {
  const CounterWidget({
    super.key,
    required this.title,
    required this.provider,
  });
  final String title;

  // 'CounterMixin' doesn't conform to the bound 'Notifier<int>'
  // of the type parameter 'NotifierT'.
  // Try using a type that is or is a subclass of 'Notifier<int>'.
  final NotifierProvider<CounterMixin, int> provider;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Expanded(
      child: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(title),
              Text('${ref.watch(provider)}'),
              ElevatedButton(
                onPressed: () => ref.read(provider.notifier).increment(),
                child: const Text('increment'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

void main() {
  runApp(
    const ProviderScope(child: MyApp()),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Row(
        children: [
          const CounterWidget(
            title: 'counter',
            provider: counterProvider,
          ),
          CounterWidget(
            title: 'counterFamily 1',
            provider: counterFamilyProvider(id: 1),
          ),
          CounterWidget(
            title: 'counterFamily 2',
            provider: counterFamilyProvider(id: 2),
          ),
        ],
      ),
    );
  }
}

The idea would be that the NotifierProvider works with the NotifierBase so as not to use $Notifier with $NotifierProvider

Thanks.

@MiniSuperDev MiniSuperDev added bug Something isn't working needs triage labels May 14, 2024
@MiniSuperDev MiniSuperDev changed the title [riverpod 3] NotifierProvider doesn't work with a BaseNotifier mixin. [riverpod 3] NotifierProvider doesn't work with a NotifierBase mixin. May 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage
Projects
None yet
Development

No branches or pull requests

2 participants