Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Issue with useEffect()/useState() rebuild, solutions work in setState() #345

Unanswered
anfernydc asked this question in Q&A
Discussion options

I have a text controller where with each key entry, I'm updating an image, hence a rebuild. I've tried a number of ways to refocus back on the text box after the rebuild from useEffect(), and while visually the focus of the text box shows, I can't actually type anything unless I click on the text box (backspace works for some reason). I'm not sure why, my understanding of the rebuild process is lacking but can't seem to get an explanation.

Tried various different adjustments in useEffect(), also would like to avoid using autofocus parameter in the text box widget (whose code I also tried to use as a reference). All the solutions I've tried, however, work fine if I stop using flutter hooks and use setState().

In the example code provided, because it's a lot more basic, I have also worked around this in this example by not using useState('') and using useListener() and wrapping the text box widget with a focus widget (doesn't work with useState), but would like to solve this using useState() as I need it for my implementation.

import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
 runApp(MyApp());
}
class MyApp extends StatelessWidget {
 MyApp({Key? key}) : super(key: key);
 @override
 Widget build(BuildContext context) {
 return FluentApp(
 title: 'Flutter Demo',
 theme: FluentThemeData(accentColor : Colors.blue,),
 home: HomePage(),
 );
 }
}
class HomePage extends HookWidget {
 const HomePage({Key? key}) : super(key: key);
 @override
 Widget build(BuildContext context) {
 final urlTextController = useTextEditingController();
 final urlTextNotif = useState('');
 final selectedIndexState = useState(0); //edit
 final selectedIndex = selectedIndexState.value; //edit
 final focusNode = useFocusNode(); 
 useEffect(() {
 focusNode.requestFocus();
 urlTextController.addListener(() {
 urlTextNotif.value = urlTextController.text;
 });
 return () {
 urlTextController.dispose();
 };
 }, [focusNode, urlTextController]);
 return NavigationView(
 pane: NavigationPane(
 items: [
 PaneItem(
 title: const Text('test'),
 body: Column(
 children: [
 TextBox(
 controller: urlTextController,
 focusNode: focusNode,
 ),
 Text('Typed text: ${urlTextNotif.value}'),
 ],
 ),
 icon: const Icon(FluentIcons.to_do_logo_outline),
 ),
 ],
 selected: selectedIndex,
 onChanged: (index) {selectedIndexState.value = index;},
 ),
 );
 }
}
You must be logged in to vote

Replies: 2 comments 6 replies

Comment options

int selectedIndex = 0;

You cannot store state as properties of your widgets like this.

You must be logged in to vote
2 replies
Comment options

Apologies, when I was splicing the code to keep it shorter, I didn't catch that.

I can get it to work if I force focusNode() to be rebuilt by adding a HookBuilder -> useEffect -> focusNode.requestFocus() inside of Column(). Not sure why the above implementation of useEffect() doesn't work.

Comment options

Thank you for bug fixes regarding widget focus, this code now works without any changes.

Comment options

@anfernydc what was the fix for you? I think I'm running into a similar issue. Here's my snippet. I have a widget to edit definition, but when a value is fetched from workoutProvider it should replace the definition with the fetched value and rebuild

 final fetchedWorkout = ref.watch(workoutProvider); // returns AsyncValue<WorkoutDefinition>
 final definition = useState(null as WorkoutDefinition?);
 
 useEffect(() {
 fetchedWorkout.when(
 data: (data) => definition.value = data, // <-- this is being hit correctly but the widget is not rebuilt
 error: (error, stackTrace) { /* show error */ },
 loading: () => definition.value = null,
 );
 return null;
 }, [fetchedWorkout]);
You must be logged in to vote
4 replies
Comment options

Actually after re-reading, it sounds like your update of the value notifier was re-building correctly, so this isn't the same issue

Comment options

My first guess was that the captured definition value provider in the when -> data callback is stale, although its hashcode matches the hashcode from the first build and when it rebuilds after workoutProvider updates.

@rrousselGit am I doing something wrong here?

Comment options

Found my issue, I needed to wrap my update in a Future.microtask as described here #153

And I ended up refactoring to do the update prior to the build as suggested in the comments

Comment options

Sorry just saw your comment in my email now, good to hear you worked it out! I might end up running into a similar issue so I'm thankful you mentioned how you got it to work. At the time I also ran into focusNode and useEffect having some conflicts, left that alone, and one day after Flutter/hooks was updated, it just worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /