如何定义依赖于Provider的GoRouter?

2024-01-09

我正在将 GoRouter 集成到我的 Flutter 应用程序中,我已经在使用 Riverpod。我有一个isAuthorizedProvider定义如下:

final isAuthorizedProvider = Provider<bool>((ref) {
  final authStateChanged = ref.watch(_authStateChangedProvider);
  final user = authStateChanged.asData?.value;
  return user != null;
});

而且我不确定如何定义依赖于上面的 Provider 的 GoRouter。我想出了以下几点:

final goRouterProvider = Provider<GoRouter>((ref) => GoRouter(
      debugLogDiagnostics: true,
      redirect: (state) {
        final isAuthorized = ref.watch(isAuthorizedProvider);
        final isSigningIn = state.subloc == state.namedLocation('sign_in');

        if (!isAuthorized) {
          return isSigningIn ? null : state.namedLocation('sign_in');
        }

        // if the user is logged in but still on the login page, send them to
        // the home page
        if (isSigningIn) return '/';

        // no need to redirect at all
        return null;
      },
      routes: [
        GoRoute(
          path: '/',
          ...,
        ),
        GoRoute(
          name: 'sign_in',
          path: '/sign_in',
          ...,
        ),
        GoRoute(
            name: 'main',
            path: '/main',
            ...,
        ),
        ...
      ],
    ));

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final goRouter = ref.watch(goRouterProvider);
    return MaterialApp.router(
      routeInformationParser: goRouter.routeInformationParser,
      routerDelegate: goRouter.routerDelegate,
    );
  }

这是正确的做法吗?


我认为你不应该拨打这条线

ref.watch(isAuthorizedProvider);

在重定向块内,因为这会导致你的整个GoRouter要重建的实例(并且您将丢失整个导航堆栈)。

我就是这样做的:

class AppRouterListenable extends ChangeNotifier {
  AppRouterListenable({required this.authRepository}) {
    _authStateSubscription =
        authRepository.authStateChanges().listen((appUser) {
      _isLoggedIn = appUser != null;
      notifyListeners();
    });
  }
  final AuthRepository authRepository;
  late final StreamSubscription<AppUser?> _authStateSubscription;
  var _isLoggedIn = false;
  bool get isLoggedIn => _isLoggedIn;

  @override
  void dispose() {
    _authStateSubscription.cancel();
    super.dispose();
  }
}

final appRouterListenableProvider =
    ChangeNotifierProvider<AppRouterListenable>((ref) {
  final authRepository = ref.watch(authRepositoryProvider);
  return AppRouterListenable(authRepository: authRepository);
});

final goRouterProvider = Provider<GoRouter>((ref) {
  final authRepository = ref.watch(authRepositoryProvider);
  final appRouterListenable =
      AppRouterListenable(authRepository: authRepository);
  return GoRouter(
    debugLogDiagnostics: false,
    initialLocation: '/',
    redirect: (state) {
      if (appRouterListenable.isLoggedIn) {
        // on login complete, redirect to home
        if (state.location == '/signIn') {
          return '/';
        }
      } else {
        // on logout complete, redirect to home
        if (state.location == '/account') {
          return '/';
        }
        // TODO: Only allow admin pages if user is admin (#125)
        if (state.location.startsWith('/admin') ||
            state.location.startsWith('/orders')) {
          return '/';
        }
      }
      // disallow card payment screen if not on web
      if (!kIsWeb) {
        if (state.location == '/cart/checkout/card') {
          return '/cart/checkout';
        }
      }
      return null;
    },
    routes: [],
  );
}

请注意,这段代码是不反应从某种意义上说,当 authState 更改时它将刷新路由器。因此,与此相结合,您需要在登录/注销时执行显式导航事件。

或者,您可以使用refreshListenable争论。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何定义依赖于Provider的GoRouter? 的相关文章

随机推荐

  • rmi java.security.policy 访问被拒绝

    我是 Java 中的 RMI 主题新手 我想使用 RMI 创建客户端服务器应用程序 我按照此链接中找到的本教程进行操作 使用 eclipse 的 RMI 教程 http www ejbtutorial com java rmi a step
  • 分组并计算 Javascript 数组中属性的平均值

    我很难在其他 stackoverflow 帖子中找到我正在寻找的解决方案 尽管我强烈地觉得它必须存在 如果是的话 请把我转发到正确的方向 我正在尝试使用运动数据在 javascript 中做一个非常标准的分组 我有以下对象数组 const
  • 如何在Python中拆分数学表达式的字符串?

    我制作了一个在 python 中将中缀转换为后缀的程序 问题是当我介绍论点时 如果我引入这样的内容 这将是一个字符串 73 34 72 33 3 56 95 28 它会用 split 分割它 程序将正常工作 但我希望用户能够介绍这样的内容
  • iOS 6 社交框架无法设置或没有警报

    我正在尝试在 iOS6 中实现新的社交框架 并让它正常工作 除了两个奇怪的问题 如果我启用了我感兴趣的服务 例如 FaceBook 那么它就可以正常工作 但是 如果从设置面板 假设是 Facebook 为了保持一致 中删除了帐户 那么我会在
  • 如何在 MATLAB 的 bar3 图中隐藏零值

    我有一个 2 D 直方图 该图是 3D 的 几个并排绘制的直方图 是用 bar3plot 命令生成的 然而 所有零值在 x y 平面上都显示为平面正方形 有没有办法阻止 MATLAB 显示这些值 我已经尝试用 NaN 替换所有零 但它并没有
  • 如何在 OpenUrl 卡操作中回复消息?

    我正在发送带有 openURL 的 cardAction 用户应该单击该按钮 按照所述 URL 中的说明进行操作 然后报告数据 我想要显示一条消息when用户单击按钮 同时打开 URL 根据我的测试 我只能选择 ImBack 或 OpenU
  • 如何在 Google Cloud BigQuery 中小写整个列数据

    我正在尝试找到一种 快速 方法来小写 Google Cloud BigQuery 内表列中的所有数据 字符串 在构建脚本之前 我正在寻找更短的方法 例如查询 如何查询 BigQuery 以小写整个列 您可以使用UPDATE陈述 UPDATE
  • MySQL UPDATE 和 SELECT 一次性完成

    我有一个要执行的 MySQL 任务表 每一行都有一个任务的参数 有许多工作应用程序 可能在不同的机器上 循环执行任务 这些应用程序使用 MySQL 的本机 C API 访问数据库 为了拥有一项任务 应用程序会执行以下操作 生成一个全局唯一的
  • 类型参数命名准则是什么?

    我注意到了 也看到了必备 C 3 0 https rads stackoverflow com amzn click com 0321533925书上 参数通常定义为T or TEntity 例如 public class Stack
  • !: Angular 中的(爆炸冒号)表示法

    I found 中使用的符号Angular 弃用文档 https angular io guide deprecations dependency on a reflect metadata polyfill in jit mode Inp
  • TextField 包含日语字符时缺少字体样式

    将字符串传递给视图 Case 1 English alphabet is no problem test deck ABCDE Case 2 Font style is missing test deck Case 3 Font style
  • 用于比较 Windows 二进制文件的工具?

    我们的 QA 团队希望根据 EXE 和 DLL 在构建之间实际发生的变化来集中测试 我们有一个很好的 svn 更改报告 但是源代码和更改的二进制文件之间的关系并不总是很明显 我们正在比较的构建始终是完全干净的构建 因此我们不能使用文件系统时
  • Python 基础知识 为什么 set() 有效但 {} 失败? [复制]

    这个问题在这里已经有答案了 s this that this 为什么set s 工作但是 s 失败了 TypeError unhashable type list 这是因为它们意味着不同的东西 set s 迭代s创建一个集合 而文字语法 s
  • 如何定期使用 PAPI 进行性能测量

    我想使用 C 中的 PAPI api 分析我的应用程序的系统性能 一般结构是 初始化PAPI 初始化感兴趣的计数器 启动计数器 运行应用程序的主要逻辑 结束计数器并读取值 我想定期读取计数器 例如每 1 秒一次 而不是在应用程序结束时读取最
  • OData 筛选器和 Guid 字段的问题

    我正在尝试使用 OData 来运行一些代码 下面的代码似乎不起作用 ds是 OpenDataServiceProxy 适配器类型 ID是 Guid 的字符串表示形式 适配器名称是一个字符串名称 ds query DataAdapters f
  • 如何解决 Node.js 错误:找不到模块?

    当我启动一个 dockerized Node js 测试应用程序时 sudo docker compose up 我收到以下错误 Starting testapp web 1 done Attaching to testapp web 1
  • AWS S3分段上传在不指定源文件时工作

    我已经构建了一个 ajax 上传器 可以将文件直接上传到 S3 它运行完美 但我感到困惑的是它实际上是如何工作的 我对文档中的显示方式采取了不同的方法 不是指定 sourceFile 而是在元数据中指定文件名 没有发送文件位置 我在用着AW
  • Laravel 和 LocalStack 的最大执行时间

    我正在尝试使用 Localstack 来模拟 s3 实例 以便我可以从表单上传图像 这是我的 docker compose localstack image localstack localstack latest container na
  • 如何使用 Ruby/Rails 从网站获取内容?

    我想使用 ruby rails 从网站复制一些特定内容 我需要的内容位于一个 marquee html 标签内 由 div 分隔 我如何使用 ruby 访问此内容 更准确地说 我想使用某种 ruby gui 最好是鞋子 我该怎么做 这并不是
  • 如何定义依赖于Provider的GoRouter?

    我正在将 GoRouter 集成到我的 Flutter 应用程序中 我已经在使用 Riverpod 我有一个isAuthorizedProvider定义如下 final isAuthorizedProvider Provider