flutter_hooks icon indicating copy to clipboard operation
flutter_hooks copied to clipboard

Add useRouteAware hook

Open changalberto opened this issue 4 years ago • 3 comments

I'm in need of a RouteAware hook for a HookWidget to observer for route changes and make state updates. This would be a good tutorial/example of what some of use cases would be: https://medium.com/flutter-community/how-to-track-screen-transitions-in-flutter-with-routeobserver-733984a90dea But I'm stuck trying to figure out how to create a hook for it. Some guidance on how to structure this would be appreciated.

changalberto avatar Aug 11 '20 04:08 changalberto

You can create a separate class:

class Example extends RouteAware {
  @override
  // Called when the current route has been pushed.
  void didPush() {
    print('didPush');
  }
}

...
final route = ModalRoute.of(context);

useEffect(() {
  final example = Example();
  routeObserver.subscribe(example, route);
  return () => routeObserver.unsubscribe(example);
}, [route, routeObserver]);

rrousselGit avatar Sep 19 '20 12:09 rrousselGit

I would suggest getting acquainted with wouter, maybe its API will inspire you.

AlexandraOlegovna avatar Oct 25 '20 09:10 AlexandraOlegovna

Just in case someone stumbles upon this, here is something I'm using based around the example above.

It is using Option from the dartz package, so you might want to replace that with nullable types.

import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class _RouteCallbacks with RouteAware {
  const _RouteCallbacks({
    this.handleDidPopNext = const None(),
    this.handleDidPush = const None(),
    this.handleDidPop = const None(),
    this.handleDidPushNext = const None(),
  });

  final Option<VoidCallback> handleDidPopNext;
  final Option<VoidCallback> handleDidPush;
  final Option<VoidCallback> handleDidPop;
  final Option<VoidCallback> handleDidPushNext;

  @override
  void didPopNext() {
    handleDidPopNext.map((f) => f());
  }

  @override
  void didPush() {
    handleDidPush.map((f) => f());
  }

  @override
  void didPop() {
    handleDidPop.map((f) => f());
  }

  @override
  void didPushNext() {
    handleDidPushNext.map((f) => f());
  }
}

void useRouteObserver(
  RouteObserver<ModalRoute> routeObserver, {
  Option<VoidCallback> didPopNext = const None(),
  Option<VoidCallback> didPush = const None(),
  Option<VoidCallback> didPop = const None(),
  Option<VoidCallback> didPushNext = const None(),
  List<Object?> keys = const [],
}) {
  final context = useContext();
  final route = ModalRoute.of(context);

  useEffect(() {
    if (route == null) return () {};

    final callbacks = _RouteCallbacks(
      handleDidPop: didPop,
      handleDidPopNext: didPopNext,
      handleDidPush: didPush,
      handleDidPushNext: didPushNext,
    );
    routeObserver.subscribe(callbacks, route);
    return () => routeObserver.unsubscribe(callbacks);
  }, [route, routeObserver, ...keys]);
}

tim-smart avatar Mar 26 '21 08:03 tim-smart