Issue
I'm pretty new to flutter_bloc library and i'm trying to make component of increment decrement button but when I tried to duplicate the component, i face the problem, when I push the second increment button component the first component updated too like this result. I want them to have separated result. how can i fix that?
here is my bloc code:
import 'package:bloc/bloc.dart';
abstract class QtyEvent{}
class Increment extends QtyEvent {}
class Decrement extends QtyEvent {}
class QtyBloc extends Bloc<QtyEvent, int> {
QtyBloc() : super(0) {
on<Increment>((event, emit) =>
emit(state+1));
on<Decrement>((event, emit) =>
emit(state-1));
}
}
and here is my component code:
class _QtyState extends State<Qty> {
int _n = 0;
@override
void add() {
setState(() {
_n++;
});
context.read<QtyBloc>().add(Increment());
}
void minus() {
setState(() {
if (_n != 0) _n--;
});
context.read<QtyBloc>().add(Decrement());
}
QtyBloc qtybloc = QtyBloc();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),),
body: Column(
children: [
Row(
children: [
GestureDetector(
onTap: minus,
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: Icon(Icons.remove),
),
),
Text(
context.watch<QtyBloc>().state.toString(),
style: TextStyle(fontSize: 20),
),
GestureDetector(
onTap: add,
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: Icon(Icons.add),
),
),
],
),
],
),
);
}
}
Solution
your code is doing exactly what it was designed to do.
If I understand correctly, you want to use the same Bloc to have two sets of increment
& decrement
buttons?
Since you are emitting
a single state
, when you update it in one place, it updates everywhere!
Also, you do not need to call setState
as it re renders the UI which can be achieved by bloc it self.
And, in the heading you mentioned you use flutter_bloc
but in your code, you are using bloc
.
Here is how to implement it with flutter_bloc
,
logic.dart
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterEvent {
const CounterEvent();
}
class Increment extends CounterEvent {
final int value1, value2;
const Increment({this.value1 = 1, this.value2 = 1});
}
class Decrement extends CounterEvent {
final int value1, value2;
const Decrement({this.value1 = 1, this.value2 = 1});
}
class Reset extends CounterEvent {
final int value;
const Reset({this.value = 0});
}
class CounterState {
final int s1, s2; // Just maintain 2 values!
const CounterState({required this.s1, required this.s2});
}
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc(CounterState initialState) : super(initialState);
@override
Stream<CounterState> mapEventToState(CounterEvent event) async* {
if (event is Increment) {
yield CounterState(
s1: state.s1 + event.value1, s2: state.s2 + event.value2);
} else if (event is Decrement) {
yield CounterState(
s1: state.s1 - event.value1, s2: state.s2 - event.value2);
} else if (event is Reset) {
yield CounterState(s1: event.value, s2: event.value);
}
}
}
component_page.dart
class Component extends StatelessWidget {
const Component({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Counter'),
),
body: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Column(
children: [
Row(
children: [
GestureDetector(
onTap: () {
BlocProvider.of<CounterBloc>(context)
.add(const Decrement(value1: 1, value2: 0));
},
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: const Icon(Icons.remove),
),
),
Text(
state.s1.toString(),
style: const TextStyle(fontSize: 20, color: Colors.white),
),
GestureDetector(
onTap: () {
BlocProvider.of<CounterBloc>(context)
.add(const Increment(value1: 1, value2: 0));
},
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: const Icon(Icons.add),
),
),
],
),
Row(
children: [
GestureDetector(
onTap: () {
BlocProvider.of<CounterBloc>(context)
.add(const Decrement(value1: 0, value2: 1));
},
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: const Icon(Icons.remove),
),
),
Text(
state.s2.toString(),
style: const TextStyle(fontSize: 20, color: Colors.white),
),
GestureDetector(
onTap: () {
BlocProvider.of<CounterBloc>(context)
.add(const Increment(value1: 0, value2: 1));
},
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: const Icon(Icons.add),
),
),
],
),
Row(
children: [
GestureDetector(
onTap: () {
BlocProvider.of<CounterBloc>(context)
.add(const Reset(value: 0));
},
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.red),
child: const Icon(Icons.refresh),
),
),
],
),
],
);
},
),
);
}
}
Note
- This code is written with null safety
- Remember to add
BlocProvider
around your app, like so:
main.dart
void main() async {
runApp(const App());
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider<CounterBloc>(
create: (_) => CounterBloc(const CounterState(s1: 0, s2: 0)),
child: const MaterialApp(
debugShowCheckedModeBanner: false,
home: Component(),
),
);
}
}
Answered By - Nithin Sai
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.