I have a Text()
widget that displays a DateTime
as a String
. This Text()
widget is wrapped with a GestureDetecture()
where the onTap
should update the DateTime
by one day:
GestureDetector(
child: File2(
dateTime: date,
key: Key(date.toString()),
),
onTap: () {
setState(() {
// This is adding seconds not days
date = date.add(const Duration(days: 1));
});
},
),
However, the date is not updating by one day although I'm doing:
date = date.add(const Duration(days: 1));
It is however updating by a few seconds. Why isn't it updating by 1 day?
What I tried:
Using a Key()
Code:
file_1.dart
:
import 'package:flutter/material.dart';
import 'file_2.dart';
void main() {
runApp(File1());
}
class File1 extends StatefulWidget {
const File1({Key? key}) : super(key: key);
@override
State<File1> createState() => _File1State();
}
class _File1State extends State<File1> {
@override
Widget build(BuildContext context) {
DateTime date = DateTime.now();
return MaterialApp(
home: Scaffold(
body: Center(
child: GestureDetector(
child: File2(
dateTime: date,
key: Key(date.toString()),
),
onTap: () {
setState(() {
// This is adding seconds not days
date = date.add(const Duration(days: 1));
});
},
),
),
),
);
}
}
file_2.dart
:
import 'package:flutter/material.dart';
class File2 extends StatelessWidget {
DateTime dateTime;
File2({Key? key, required this.dateTime}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(dateTime.toString());
}
}
How can I update the
Text()
inFile2
by 1 day when clicking on theGestureDetector()
?Do I need to use a statemanagement other then
setState()
?
CodePudding user response:
Problem
This error occurs simply because you have this line at the beginning of the build method: DateTime date = DateTime.now();
.
This is the workflow of what is happening in your code:
- You set the date value to
DateTime.now()
at the beginning of the build method. - This current date value is rendered in your UI.
- You trigger the function to update your date.
- 1 day is added to the date.
- IMPORTANT: Step 4 triggers the rebuild of your widget, hence Step 1 is executed again.
As a result of Step 5, the date value just gets updated for a moment, but then the DateTime.now()
is rendered in UI.
Solution
Initiate the date
value in your State class and not in the build method. This way, your date
value won't be overwritten by the Widget rebuild:
class _File1State extends State<File1> {
DateTime date = DateTime.now(); // <-- Initiate the value here
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: GestureDetector(
child: File2(
dateTime: date,
key: Key(date.toString()),
),
onTap: () {
setState(() {
// This is adding seconds not days
date = date.add(const Duration(days: 1));
});
},
),
),
),
);
}
}