1
resposta

erro no dropdown ao dar hot reload

Tenho uma tela para cadastrar um novo gasto. Nessa tela, tem um dropdown pra selecionar a categoria do gasto.

tela de gasto com nenhuma categoria selecionada

Acontece que, ao selecionar uma categoria e, em seguida, dar Hot Reload, dá erro.

tela de gasto com a categoria comida selecionada

imagem com a descrição do erro

Note que o erro fala que existem mais de um DropdownMenuItem com o mesmo valor: o objeto do tipo Categoria que havia sido selecionado antes do hot reload. Note também que esse erro não é gerado caso nenhuma categoria tenha sido selecionada antes de efetuar o hot reload.

A seguir o código da classe referente ao dropdown + o indicador da cor da categoria selecionada:

import 'package:bytebank/models/categoria.dart';
import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';

class SeletorCategoria extends StatefulWidget {
  final List<Categoria> categorias = [
    Categoria('Bebida', Colors.red),
    Categoria('Comida', Colors.blue),
    Categoria('Carro', Colors.green),
  ];

  SeletorCategoria({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return SeletorCategoriaState();
  }
}

class SeletorCategoriaState extends State<SeletorCategoria> {
  Categoria? dropdownValue;
  late Color selectedColor = Theme.of(context).scaffoldBackgroundColor;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Flexible(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: DropdownButtonHideUnderline(
              child: DropdownButtonFormField<Categoria>(
                value: dropdownValue,
                style: const TextStyle(fontSize: 24.0),
                items: widget.categorias.map((categoria) {
                  return DropdownMenuItem<Categoria>(
                    value: categoria,
                    child: Padding(
                      padding: const EdgeInsets.only(left: 8.0),
                      child: Text(categoria.name),
                    ),
                  );
                }).toList(),
                onChanged: (categoria) {
                  setState(() {
                    dropdownValue = categoria!;
                    selectedColor = categoria.color;
                  });
                },
                isExpanded: true,
                decoration: const InputDecoration(
                  labelText: 'Categoria',
                  labelStyle: TextStyle(fontSize: 24.0),
                  alignLabelWithHint: true,
                  border: OutlineInputBorder(),
                ),
              ),
            ),
          ),
        ),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: ColorIndicator(HSVColor.fromColor(selectedColor)),
        ),
      ],
    );
  }
}

Alguém saberia explicar o motivo desse erro estar acontecendo e uma possível solução?

Grato.

1 resposta

Olá Gabriel, tudo bem?

Pelo que entendi, o erro ocorre quando você seleciona uma categoria no dropdown e, em seguida, faz um hot reload. Isso acontece porque o hot reload recarrega o widget, mas não recria o estado dele. Então, quando você seleciona uma categoria, o estado do dropdown é atualizado, mas quando você faz o hot reload, o estado antigo é mantido e o dropdown tenta recriar os itens com base no estado antigo, o que causa o erro de ter mais de um DropdownMenuItem com o mesmo valor.

Uma possível solução para esse problema é utilizar a chave (key) do widget para forçar a recriação do estado do dropdown quando o hot reload é executado. Para isso, você pode criar uma chave única para o widget e passá-la para o construtor do widget. Por exemplo:

class SeletorCategoria extends StatefulWidget {
  final List<Categoria> categorias = [
    Categoria('Bebida', Colors.red),
    Categoria('Comida', Colors.blue),
    Categoria('Carro', Colors.green),
  ];

  SeletorCategoria({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return SeletorCategoriaState();
  }
}

E na hora de criar o widget, você pode passar a chave única:

SeletorCategoria(key: UniqueKey())

Dessa forma, quando o hot reload é executado, o widget é recriado com um novo estado e o erro não deve mais ocorrer.

Espero ter ajudado e bons estudos!