import 'package:fl_query/models/mutation_job.dart'; import 'package:fl_query/mutation.dart'; import 'package:fl_query/query_bowl.dart'; import 'package:flutter/widgets.dart'; class MutationBuilder extends StatefulWidget { final Function(BuildContext, Mutation) builder; final MutationJob job; /// Called when the query returns new data, on query /// refetch or query gets expired final MutationListener? onData; /// Called when the query returns error final MutationListener? onError; /// called right before the mutation is about to run /// /// perfect scenario for doing optimistic updates final MutationListener? onMutate; const MutationBuilder({ required this.job, required this.builder, this.onData, this.onError, this.onMutate, Key? key, }) : super(key: key); @override State> createState() => _MutationBuilderState(); } class _MutationBuilderState extends State> { late QueryBowl queryBowl; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { queryBowl = QueryBowl.of(context); queryBowl.addMutation( widget.job, onData: widget.onData, onError: widget.onError, onMutate: widget.onMutate, mount: widget, ); }); } @override void dispose() { final mutation = queryBowl.getMutation(widget.job.mutationKey); mutation?.unmount(widget); if (widget.onData != null) mutation?.onDataListeners.remove(widget.onData); if (widget.onError != null) mutation?.onErrorListeners.remove(widget.onError); if (widget.onMutate != null) mutation?.onMutateListeners.remove(widget.onMutate); super.dispose(); } @override Widget build(BuildContext context) { queryBowl = QueryBowl.of(context); final mutation = queryBowl.getMutation(widget.job.mutationKey); if (mutation == null) return Container(); return widget.builder(context, mutation); } }