How to reload data when using useFuture flutter hook - flutter

I'm using Flutter hooks to fetch data by combining useMemorized and useFuture like this:
final _latestDocsFuture =
useMemoized(() => getLatestDocs());
final _latesetDocsSnapshot = useFuture(_latestDocsFuture);
The problem with this hook is I can't re-trigger the useFuture to re-fetch the data in case of an error (allowing the user to tap on a button to try and fetch the data again).
Is there any method that can let me re-trigger the useFuture hook?

The useMemoized hook accepts a list of keys that can be used to create new instances of the Future, which would cause useFuture to run again.
I'd suggest using the UniqueKey class to achieve this
final reloadKey = useState(UniqueKey());
final latestDocsFuture = useMemoized(() => getLatestDocs(), [reloadKey.value],);
final latestDocsSnapshot = useFuture(latestDocsFuture);
Then whenever you wish to reload, you can update the value of reloadKey
reloadKey.value = UniqueKey();

Related

Changes in Object from Second Screen is also Changing the Value in First Screen in flutter dart

A class Object passing from First Screen to the second Screen While on the second screen when the object changed its value, it's also changing the value on first screen.
Code of First Screen. (widget.templateModel is an object class that i am passing to the second screen)
Navigator.push(context,MaterialPageRoute(builder: (context) =>
EditEmojiTextTemplateScreen(templateModel: widget.templateModel,));
Code of Second Screen (On the second screen i am receiving the object and when i am changing the value of widget.templateModel it also changing the value on the first screen for a simple understandable code below i changed the value in initState while in the gif i am changing value in TextFormField)
class EditEmojiTextTemplateScreen extends StatefulWidget {
final TemplateModel templateModel;
EditEmojiTextTemplateScreen({
Key? key,
required this.templateModel,
}) : super(key: key);
#override
State<EditEmojiTextTemplateScreen> createState() =>
_EditEmojiTextTemplateScreenState();
}
class _EditEmojiTextTemplateScreenState
extends State<EditEmojiTextTemplateScreen> {
final SharedPreferences sharedPreferences = sl();
var txtNameController = TextEditingController();
var txtColorController = TextEditingController();
_EditEmojiTextTemplateScreenState();
#override
void initState() {
widget.templateModel.emoji[0].titleTwo = "kdfff"; //here i am changing the value and it also changing the value on first screen and i dont want this behavior of this object
super.initState();
}
Note: This is happening because of widget variable as mentioned in the documentation but i don't know how to prevent this behavior.
package:flutter/src/widgets/framework.dart
The current configuration.
A [State] object's configuration is the corresponding [StatefulWidget]
instance. This property is initialized by the framework before calling
[initState]. If the parent updates this location in the tree to a new
widget with the same [runtimeType] and [Widget.key] as the current
configuration, the framework will update this property to refer to the
new widget and then call [didUpdateWidget], passing the old
configuration as an argument.
Now I see what you are trying to do.
You could initialize a NEW istance of TemplateModel in the InitState of the second screen.
Then, set the new object's properties like this (or write a cleaner method to do that):
newObject.property1 = oldObject.property1;
newObject.property2 = oldObject.property2;
...
Once the user presses the save button, change oldObject's properties again, so that the first page updates.
You might want to take a look at state management to better understand how to approach this kind of problems.
As the other answer suggests, take a look at state management solutions.
Also keep the models immutable by creating them with final fields. Then to modify, create new instances via copyWith()
Please update you code after navigation.then method
template = snapshot.data;

GetX Observable works with list but not custom class

I am using GetX and Firebase Realtime Database. When I use this in my GetX controller, and Update a certain value (like the username), the Obx widget in my main screen is updated. Everything works smoothly.
Rx<List<FrediUser>> frediUser = Rx<List<FrediUser>>([]);
String get username => frediUser.value.first.username;
#override
void onInit() async {
super.onInit();
User? user = Get.find<AuthController>().user;
String uid = user!.uid;
frediUser.bindStream(DatabaseManager().frediUserStream(uid));
ever(frediUser, everCalled);
}
But I only have one current user which I want to fetch, so making it a list is unnecesary. If I take the list off like so:
Rx<FrediUser?> frediUser = Rx<FrediUser?>(null); it stops working.
Of course I modify the subsequent lines to adjust for this. Or if I am using a custom class it doesn't notice the update.
Note: The stream is called (checked with a print statement), but it is as if the update never gets to the controller or the UI.
It seems as if the value is nullable, the ever function is not called.
Related question: here
Change it to the following:
Rxn<FrediUser> frediUser = Rxn<FrediUser>();
String get username => frediUser.value.first.username;

is it possible to automatically refresh component when getx value changed flutter

I am using getx get: ^4.3.8 as the state management component in flutter, when I using this code to update the controller value:
var expand = controller.newTaskExpanded.value;
controller.newTaskExpanded(!expand);
I found the component did not refresh, then I have to invoke the getx refresh function like this:
controller.refresh();
this is the controller properties define:
class HomeController extends GetxController {
List<Widget> widgetsList = List.empty(growable: true);
List<Todo> tasks = List.empty(growable: true);
var newTaskExpanded = true.obs;
var completedTaskExpanded = false.obs;
}
is is possible to auto refresh the flutter component when controller properties value changed? should I invoke the refresh function every time change the value of getx controller?
Reactive programming with Get is as easy as using setState.
Let's imagine that you have a name variable and want that every time you change it, all widgets that use it are automatically changed.
This is your count variable:
var name = 'Jonatas Borges';
To make it observable, you just need to add ".obs" to the end of it:
var name = 'Jonatas Borges'.obs;
And in the UI, when you want to show that value and update the screen whenever the values changes, simply do this:
Obx(() => Text("${controller.name}"));
For more , refer: https://pub.dev/packages/get/example
wrap you UI with Obx builder like
appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
it will auto refresh the UI on value change
if you want to refresh the UI manually then use GetBuilder and when you need to update the UI just call controller.update();
As #Muhammad Sherad explained, your widget code should be wrapped with Obx() so that you widget can look for variable change and re-render the widget.

flutter refresh obs list of classes after changing data in it

I created a list and made it observable by using using getx obs
var msgChat = List.filled(1, UserMessagesModel(), growable: true).obs;
and if i append or add a new to it, it automatically updates in the UI but my problem is that if i using a single value inside the classes of the list it doesn't get updated until i do it for the second time before it updates
socket.on("msg_delivered", (del) {
OfflineDatabaseManager.instance.updateMsgReadData(del).then((value) {
uController.msgChat.forEach((el) {
if (el.msgId == del) {
print(el.msgId);
el.isRead = 'true';
}
});
});
});
my listview is wrap using an Obx widget which makes it work but it doesn't updated if a single value in the class of the list is changed please is there a way to like refresh the list or listview and also i can't use setState(() {}); because an not inside a Statefulbuilder but in a class which extends to getx
class SocketHandler extends GetxController {}
please how do i fix this issue. Thank. Also if you require more explanation then tell me to explain
you can use refresh method like this on your observable, after changing the value:
msgChat.refresh()
if this didn't work, it's probably because you didn't use Obs correctly
please share the Obs part if the problem remains so i can help

How to pass a variable (ui object) in flutter/dart?

im a very newbie to flutter integration testing. For now I only know how to write basic sheets of finding elements on a screen and make some actions to them.
Can please anyone help me on how to pass a variable in a function if i want to reuse it? Example:
static Future<void> createProjectFromWizard(FlutterDriver driver, String projectName, bool direct) async {
final faker = new Faker();
final buttonStart = find.byValueKey(OnboardingIds.buttonStart);
await driver.waitFor(buttonStart).then((_) => driver.tap(buttonStart));
I want to reuse this function but instead of final buttonStart I need to find another ui-button. How can I do this without re-writing this function? (Because it is a very long one, i pasted a short piece)