Skip to content

Multiple BeamLocations with same subclass breaks page rendering. #658

@jwalton

Description

@jwalton

Describe the bug

If you have two ore more BeamLocations that are of the same subclass, page rendering is broken. Navigating to links works, but the content on screen doesn't change.

Beamer version: 1.6.0

To Reproduce

This creates two instances of SimpleLocation, which is just a BeamLocation where you pass in a path pattern, a key, and a child. The two SimpleLocations ought to allow routing to /a and /b, but it doesn't work. If you try to click the button to go to "/b", the URL changes if you're on Web, but the content of the page doesn't change.

If you copy-paste the SimpleLocation class to a SimpleLocation2 class, and change the "BScreen" route to use SimpleLocation2, the app will start working as expected. Somehow having two BeamLocations that are instances of the same class breaks page rendering.

import 'package:beamer/beamer.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class SimpleLocation extends BeamLocation<BeamState> {
  final List<String> _pathPatterns;
  final ValueKey _key;
  final Widget child;

  SimpleLocation(String path, String key, this.child)
      : _pathPatterns = [path],
        _key = ValueKey(key);

  @override
  List<String> get pathPatterns => _pathPatterns;

  @override
  List<BeamPage> buildPages(BuildContext context, BeamState state) {
    return [
      BeamPage(
        key: _key,
        child: child,
      ),
    ];
  }
}

class MyApp extends StatelessWidget {
  MyApp({super.key});

  final routerDelegate = BeamerDelegate(
    initialPath: '/a',
    // locationBuilder: RoutesLocationBuilder(
    //   routes: {
    //     // Return either Widgets or BeamPages if more customization is needed
    //     '/a': (context, state, data) => AScreen(),
    //     '/b': (context, state, data) => BScreen(),
    //   },
    // ),
    locationBuilder: BeamerLocationBuilder(
      beamLocations: [
        SimpleLocation('/a', 'a', AScreen()),
        SimpleLocation('/b', 'b', BScreen()),
      ],
    ).call,
  );
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      routeInformationParser: BeamerParser(),
      routerDelegate: routerDelegate,
    );
  }
}

class AScreen extends StatelessWidget {
  AScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('A Screen'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Beamer.of(context).beamToNamed('/b');
          },
          child: const Text('Go to B'),
        ),
      ),
    );
  }
}

class BScreen extends StatelessWidget {
  BScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('B Screen'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Beamer.of(context).beamToNamed('/a');
          },
          child: const Text('Go to A'),
        ),
      ),
    );
  }
}

Expected behavior

BeamLocations should work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions