Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Solves the problem of a module with children that does not dispose #911

Merged
merged 1 commit into from
Mar 25, 2024

Conversation

eduardoflorence
Copy link

Description

Ao navegar para uma rota filha, a rota mãe também é colocada na pilha e acrescentada para ser descartada (List _disposeTags). O problema acontece quando navegamos para uma segunda rota folha, pois era acrescentada novamente a rota mãe para descarte, causando duplicidade, então a rota mãe nunca era descartada devido a existência de mais de uma ocorrência para descarte.

Checklist

  • The title of my PR starts with a [Conventional Commit] prefix (fix:, feat:, docs: etc).
  • I have read the [Contributor Guide] and followed the process outlined for submitting PRs.

Breaking Change

  • Yes, this is a breaking change.
  • No, this is not a breaking change.

Related Issues

#902
#899

@eduardoflorence
Copy link
Author

Código exemplo utilizado para teste com Navigate (com children) e pushNamed (sem children):

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

void main() {
  runApp(ModularApp(module: AppModule(), child: const AppWidget()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: Modular.routerConfig,
    );
  }
}

class AppModule extends Module {
  @override
  void routes(r) {
    r.child('/', child: (_) => const LoginPage());
    r.module('/main', module: MainModule());
    r.module('/config', module: ConfigModule());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => Modular.to.navigate('/main/'),
              child: const Text('Login'),
            ),
            ElevatedButton(
              onPressed: () => Modular.to.pushNamed('/config/'),
              child: const Text('Configuration'),
            ),
          ],
        ),
      ),
    );
  }
}

class MainModule extends Module {
  @override
  void routes(r) {
    r.child(
      '/',
      child: (_) => const MainPage(),
      children: [
        ModuleRoute('/products', module: ProductModule()),
        ModuleRoute('/customers', module: CustomerModule()),
      ],
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('App')),
      body: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(
                onPressed: () => Modular.to.navigate('/main/products/'),
                child: const Text('Products'),
              ),
              ElevatedButton(
                onPressed: () => Modular.to.navigate('/main/customers/'),
                child: const Text('Customers'),
              ),
              ElevatedButton(
                onPressed: () {
                  Modular.to.navigate('/');
                },
                child: const Text('Logout'),
              ),
            ],
          ),
          const Expanded(child: RouterOutlet()),
        ],
      ),
    );
  }
}

class ProductModule extends Module {
  @override
  void routes(r) {
    r.child('/', child: (_) => const ProductPage());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: Text('Products List')),
    );
  }
}

class CustomerModule extends Module {
  @override
  void routes(r) {
    r.child('/', child: (_) => const CustomerPage());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: Text('Customers List')),
    );
  }
}

class ConfigModule extends Module {
  @override
  void routes(r) {
    r.child('/', child: (_) => const ConfigPage());
    r.module('/step1', module: Step1Module());
    r.module('/step2', module: Step2Module());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Config')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Modular.to.pushNamed('/config/step1/'),
          child: const Text('Go Step 1'),
        ),
      ),
    );
  }
}

class Step1Module extends Module {
  @override
  void routes(r) {
    r.child('/', child: (_) => const Step1Page());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Step1')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Modular.to.pushNamed('/config/step2/'),
          child: const Text('Go Step2'),
        ),
      ),
    );
  }
}

class Step2Module extends Module {
  @override
  void routes(r) {
    r.child('/', child: (_) => const Step2Page());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Step2')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Modular.to.pushNamed('/config/step1/'),
          child: const Text('Go Step1 again'),
        ),
      ),
    );
  }
}

@migdev-br
Copy link

@eduardoflorence tudo bem? Como ficou essa questão? O módulo principal ainda permanece ativo após navegar para rotas filhas e sair.

@eduardoflorence
Copy link
Author

@eduardoflorence tudo bem? Como ficou essa questão? O módulo principal ainda permanece ativo após navegar para rotas filhas e sair.

Na versão atual ainda permanece, pois esse PR ainda não foi aprovado

@migdev-br
Copy link

@eduardoflorence tudo bem? Como ficou essa questão? O módulo principal ainda permanece ativo após navegar para rotas filhas e sair.

Na versão atual ainda permanece, pois esse PR ainda não foi aprovado

Alguma sugestão paliativa, até esse PR ser aprovado?

@eduardoflorence
Copy link
Author

Bom dia, @migdev-br
A alteração desse PR é pequena e só no modular_core, então você pode só acrescentar as linhas abaixo no seu pubspec.yaml (não precisa alterar a dependência flutter_modular) depois das dependências:

dependency_overrides:
  modular_core:
    git: 
      url: https://github.com/eduardoflorence/modular.git
      ref: module_not_dispose
      path: modular_core

@migdev-br
Copy link

Bom dia, @migdev-br A alteração desse PR é pequena e só no modular_core, então você pode só acrescentar as linhas abaixo no seu pubspec.yaml (não precisa alterar a dependência flutter_modular) depois das dependências:

dependency_overrides:
  modular_core:
    git: 
      url: https://github.com/eduardoflorence/modular.git
      ref: module_not_dispose
      path: modular_core

vou tentar rodar.
muito obrigado!

@migdev-br
Copy link

@eduardoflorence o dispose até funciona, porém de alguma forma eu perco o estado do meu CoreModule. Quando o usuário faz login eu guardo algumas variáveis na store do core module, e quando navego por exemplo da home, para outra página/módulo,
eu perco o estado da store do CoreModule.

@edugemini
Copy link
Contributor

@migdev-br, você importa o seu CoreModule no AppModule também? O bind da sua store está como singleton para ele manter só uma instância para todo o App?

@migdev-br
Copy link

@migdev-br, você importa o seu CoreModule no AppModule também? O bind da sua store está como singleton para ele manter só uma instância para todo o App?

sim, importei no AppModule e está como singleton. Fiz um exemplo aqui, da uma olha quando puder por favor,
testa sem adicionar o seu dependency_overrides e depois testa adicionando.

https://github.com/migdev-br/new_modular

@jacobaraujo7
Copy link
Contributor

Desculpa a demora pessoal.
Problemas pessoais.
Estou de volta a ativa

@jacobaraujo7 jacobaraujo7 merged commit 7dc9c1f into Flutterando:master Mar 25, 2024
1 check passed
@migdev-br
Copy link

migdev-br commented Apr 9, 2024

Pessoal, alguma novidade? Conseguiram dar uma olhada no exemplo?
Obrigado

@eduardoflorence
Copy link
Author

@migdev-br, consegui analisar seu exemplo e vi onde estava o problema. Havia um diferença entre o modular_core que estava publicado com o do repositório, então meu repositório forcado provocava esse erro que citou. Já coloquei um novo PR para ser aprovado, mas se quiser testar, e só alterar aquele overrides que te passei para ficar com o novo branch:

dependency_overrides:
  modular_core:
    git:
      url: https://github.com/eduardoflorence/modular.git
      ref: bug-create-exported-injector
      path: modular_core

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants