It's a bit hard for me to tell what you're trying to do, but here are some possibilities.
A) someDate changes because of something that happens to the parent widget. For example, if FoobarWidget's job is just to display the date in a fancy way, then when the parent rebuilds, it can create a new instance of FoobarWidget with the new state. In this case, you can just use a simple StatelessWidget:
class FoobarWidgetA extends StatelessWidget {
final DateTime someDate;
FoobarWidget({ Key key, this.someDate }) : super(key: key);
@override
Widget build(BuildContext context) {
return new Text("the date is ${someDate}");
}
}
B) someDate changes because of something that happens FoobarWidget and the parent needs to know about the new date. For example, if FoobarWidget's job is to let the user select a date, then the parent needs to be informed about which date the user has selected. In this case, a good pattern to use is the "Checkbox" pattern (see
https://docs.flutter.io/flutter/material/Checkbox-class.html). In this pattern, the parent supplies both the someDate value and a callback that FoobarWidget should call when it wants to change the value. The parent receives the new value, calls setState on itself, and rebuilds FoobarWidget with the new value, updating the UI:
class FoobarWidgetB extends StatelessWidget {
final DateTime someDate;
final ValueChanged<DateTime> onChanged;
FoobarWidget({ Key key, this.someDate }) : super(key: key);
@override
Widget build(BuildContext context) {
return new Column(
children: [
new Text("the date is ${someDate}"),
new RaisedButton(
onPressed: () {
onChanged(someDate.add(new Duration(day: 1)));
},
child: new Text("NEXT"),
),
],
);
}
}
C) someDate changes because of something that happens FoobarWidget and the parent does not need to know about the new date. For example, if FoobarWidget's job is to let the use explore the phases of the moon on various dates. In this case, a good pattern to use is the "initial value pattern". In this pattern, the parent supplies an initial value, which FoobarWidget copies into a mutable field in its State object when the state object initializes. As the user interacts with FoobarWidget, the field in the State object is mutated and setState causes FoobarWidget to rebuild with the new value. The parent is never informed of the new value and if the parent rebuilds with a new initial value, the FoobarWidget ignores the new initial value because its state machine has advanced beyond initialization:
class FoobarWidgetC extends StatefulWidget {
final DateTime initialDate;
FoobarWidget({ Key key, this.initialDate }) : super(key: key);
@override
_FoobarWidgetState createState() => new _FoobarWidgetState();
}
class _FoobarWidgetCState extends State<FoobarWidgetC> {
DateTime someDate;
@override
void initState() {
super.initState();
someDate = widget.initialDate;
}
void _advanceDate() {
setState(() {
someDate = someDate.add(new Duration(day: 1));