firebase / FirebaseUI-Flutter

Apache License 2.0
92 stars 81 forks source link

fix: null exception when header rebuid during logout #184

Closed EArminjon closed 7 months ago

EArminjon commented 7 months ago

Description

Fixed null exception.

When user define a custom avatar of the ProfileScreen which listen property of Firebase current user, the logout will trigger the rebuild of this custom avatar widget and the rebuild of ProfileScreen few time before ProfileScreen can be pop.

Actual code FORCE null safety....

Please review and merge.

Related Issues

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process. Updating the pubspec.yaml and changelogs is not required.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

lesnitsky commented 7 months ago

When user define a custom avatar of the ProfileScreen which listen property of Firebase current user, the logout will trigger the rebuild of this custom avatar widget and the rebuild of ProfileScreen

Could you please provide a code sample that I could use to reproduce this? I don't think ProfileScreen should ever be used without User object being available, maybe there is other way to fix this?

EArminjon commented 7 months ago

Bellow an unoptimized example but can reproduce the issue. If you customize more the page you could achieve to reproduce the issue during navigation redirection for example.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart' hide UserAvatar;
import 'package:flutter/material.dart';

class ProfilePage extends StatelessWidget {
  const ProfilePage({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (BuildContext context, AsyncSnapshot<User?> snap) =>
          ProfileScreen(
        appBar: AppBar(),
        avatar: Text(snap.data?.displayName?.toString() ?? ''),
      ),
    );
  }
}
lesnitsky commented 7 months ago

This example could be updated in the following way:

class ProfilePage extends StatelessWidget {
  const ProfilePage({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return ProfileScreen(
      appBar: AppBar(),
      avatar: StreamBuilder<User?>(
        stream: FirebaseAuth.instance.authStateChanges(),
        builder: (BuildContext context, AsyncSnapshot<User?> snap) =>
            Text(snap.data?.displayName?.toString() ?? ''),
      ),
    );
  }
}

so that only the relevant widget is rebuilt.

Alternatively, you could check for the user object being null in your StreamBuilder code and render some placeholder instead of ProfileScreen.

If you customize more the page you could achieve to reproduce the issue during navigation redirection for example.

I'm not sure I understand this bit, could you please elaborate?

EArminjon commented 7 months ago

This example was just an illustration. I the page rebuild during logout an exception appear. This is a weird default behavior.

lesnitsky commented 7 months ago

You can provide SignedOutAction and perform navigation to another screen:


ProfileScreen(
  actions: [
    SignedOutAction((context) {
      Navigator.pushReplacementNamed(context, '/');
    }),
  ],
  // ...
)