rrousselGit / riverpod

A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
https://riverpod.dev
MIT License
6.17k stars 943 forks source link

provider to riverpod with param #72

Closed bcihanc closed 4 years ago

bcihanc commented 4 years ago

Firstly, thanks a thousand times fot these great packages.

I wanted to move my entire project from provider to riverpod. But i’m stuck at this point.

class EditQuestionScreen extends StatelessWidget {
  EditQuestionScreen({this.question, this.answers});

  final QuestionModel question;
  final List<AnswerModel> answers;

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
        create: (context) => QuestionProvider(
            question: this.question,
            answers: this.answers),
        child: Container());
  }
}

This is my provider widget for subwidgets. Its initialize only once. How can I move this class to Hook Widget with riverpod?

rrousselGit commented 4 years ago

Local state is not supported by providers.

What is your use-case in creating the ChangeNotifier locally like that?

bcihanc commented 4 years ago

EditQuestionScreen build before firebase fetch and deserialize. Actually I just need to know, can I create global provider with widget params in riverpod?

Like this

class AHookWidget extends HookWidget {
  AHookWidget({this.question, this.answers});

  final QuestionModel question;
  final List<AnswerModel> answers;

  // i dont want local variable like this, i want global
  final aProvider = ChangeNotifierProvider(
      (ref) => QuestionProvider(question: this.question, answers: this.answers));

  @override
  Widget build(BuildContext context) {
    final provider = useProvider(aProvider);
    return Container();
  }
}

class ASubHookWidget extends HookWidget {

  @override
  Widget build(BuildContext context) {
    final provider = useProvider(aProvider);
    return Container();
  }
}
rrousselGit commented 4 years ago

No you can't

bcihanc commented 4 years ago

I'm sorry to hear that, thank you for your help anyway 😊

rrousselGit commented 4 years ago

I mean, there's likely a different way to do what you want. But I don't know your architecture.

bcihanc commented 4 years ago

may be stupid but like this

onPressed: () async {
  QuestionModel question = await api.getQuestion();
  List<AnswerModel> answers = await api.getAnswers();

  MaterialPageRoute(builder: (context) => 
    EditQuestionScreen(question: question, answers: answers));
}
class EditQuestionScreen extends StatelessWidget {
  EditQuestionScreen({this.question, this.answers});

  final QuestionModel question;
  final List<AnswerModel> answers;

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
        create: (context) => QuestionProvider(
            question: this.question,
            answers: this.answers),
        child: Container());
  }
}
rrousselGit commented 4 years ago

Put the questions and answers inside a provider Then you will be able to put your ChangeNotifier in a provider too

bcihanc commented 4 years ago

Ok, i will do that, the problem will be solved that case. Thanks again, you saved me.

bcihanc commented 4 years ago

I think ScopedProvider is the solution.

final scopedProvider = ScopedProvider<String>((_) => throw UnimplementedError());

class AWidget extends HookWidget {
  AWidget({@required this.value});
  final String value;

  @override
  Widget build(BuildContext context) {
    return ProviderScope(
      overrides: [scopedProvider.overrideWithValue(this.value)],
      child: BWidget()
     );
  }
}
class BWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final providerValue = useProvider(scopedProvider);
    return Text(providerValue);
  }
}