在尝试将WidgetRef参数添加到Flutter的build方法时出现错误。

huangapple go评论62阅读模式
英文:

Getting error when trying to add WidgetRef parameter to the build method in Flutter

问题

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends HookWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Future<DocumentSnapshot<Map<String, dynamic>>> getUserData(userId) async {
      final userData = await FirebaseFirestore.instance
          .collection('users')
          .doc(userId)
          .get();

      return userData;
    }

    final ref = useProvider(currentUserProvider.notifier);

    useEffect(() {
      if (FirebaseAuth.instance.currentUser != null) {
        final currentUserId = FirebaseAuth.instance.currentUser!.uid;

        getUserData(currentUserId).then((currentUserData) {
          var currentUser = CurrentUser(
            uid: currentUserId,
            mobile: currentUserData.data()!['mobile'],
            // some more fields
          );

          ref.updateCurrentUser(currentUser);
        });
      }

      return null;
    }, []);

    return MaterialApp(
      title: 'MyTitle',
      home: StreamBuilder(
        stream: FirebaseAuth.instance.authStateChanges(),
        builder: (ctx, snapshot) {
          if (snapshot.hasData) {
            return const TabsScreen();
          }
          return const SignInScreen();
        },
      ),
    );
  }
}

请注意,我已经更新了代码中的一些问题。现在,ref 变量已经在 useProvider 中正确获取,以便在 useEffect 中使用。此外,我还修复了构造函数的错误签名。

英文:
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends HookWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    Future&lt;DocumentSnapshot&lt;Map&lt;String, dynamic&gt;&gt;&gt; getUserData(userId) async {
      final userData = await FirebaseFirestore.instance
          .collection(&#39;users&#39;)
          .doc(userId)
          .get();

      return userData;
    }

    useEffect(() {
      if (FirebaseAuth.instance.currentUser != null) {
        final currentUserId = FirebaseAuth.instance.currentUser!.uid;

        getUserData(currentUserId).then((currentUserData) {
          var currentUser = CurrentUser(
            uid: currentUserId,
            mobile: currentUserData.data()![&#39;mobile&#39;],
            // some more fields
          );

          ref.read(currentUserProvider.notifier).updateCurrentUser(currentUser);
        });
      }

      return null;
    }, []);

    return MaterialApp(
      title: &#39;MyTitle&#39;,
      home: StreamBuilder(
        stream: FirebaseAuth.instance.authStateChanges(),
        builder: (ctx, snapshot) {
          if (snapshot.hasData) {
            return const TabsScreen();
          }
          return const SignInScreen();
        },
      ),
    );
  }
}

This is the code I have in my main.dart file. I am trying to set a state in Riverpod every time the app launches. I am using useEffect Flutter hook to achieve the same. But to set the state, I need to get ref. When I try to add a parameter WidgetRef ref to the build function, I get the following error -

'MyApp.build' ('Widget Function(BuildContext, WidgetRef)') isn't a valid override of 'StatelessWidget.build' ('Widget Function(BuildContext)').

I don't know if there is some syntax error, or if the MainApp widget should (somehow) be converted to statefulWidget, or I need to take a totally different approach to achieve what I need?

P.S.: I am importing all the required files. Just not pasted that code here.

答案1

得分: 0

事实上,如上所述,您需要使用 HookConsumerWidget 而不是 HookWidget,以便在 build 方法中访问 ref

class MyApp extends HookConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {...}
}

您还可以使用 HookConsumer 来子树化小部件:

HookConsumer(builder: (context, ref, child) {
      return Text(ref.watch(provider));
    },);
英文:

Actually, as noted above, you need to use HookConsumerWidget instead of HookWidget so that you have access to ref in the build method:

class MyApp extends HookConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {...}

You can also use HookConsumer to subtree the widget:

HookConsumer(builder: (context, ref, child) {
      return Text(ref.watch(provider));
    },);

huangapple
  • 本文由 发表于 2023年6月6日 12:16:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76411417.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定