Skip to content

Conversation

@krushnarout
Copy link
Member

@krushnarout krushnarout commented Nov 17, 2025

setState was called after the widget was already removed

fix: Added mounted checks and moved provider updates outside of setState

closes #3442

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully addresses the issue of calling setState on a disposed widget by adding mounted checks. The refactoring of _applyFilter to use a single setState call is a good improvement. However, this has led to a situation in initState where two setState calls are made in succession, which is inefficient. My review includes suggestions to consolidate these into a single call to improve performance and fully align with the goal of using a single setState.

Comment on lines 177 to +181
_applyFilter(_currentFilter);

// Mark initial load as complete
if (mounted) {
setState(() {
_isInitialLoad = false;
});
}
setState(() {
_isInitialLoad = false;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There are two separate setState calls here, one inside _applyFilter and another one here to set _isInitialLoad. This is inefficient as it causes two rebuilds. After applying the suggested change to _applyFilter to accept a callback, you can combine these into a single state update.

      _applyFilter(_currentFilter, andThen: () {
        _isInitialLoad = false;
      });

Comment on lines 192 to 216
void _applyFilter(FilterOption option) {
setState(() {
_currentFilter = option;
if (!mounted) return;

switch (option) {
case FilterOption.interesting:
_filterByCategory(MemoryCategory.interesting);
MixpanelManager().memoriesFiltered('interesting');
break;
case FilterOption.system:
_filterByCategory(MemoryCategory.system);
MixpanelManager().memoriesFiltered('system');
break;
case FilterOption.all:
_filterByCategory(null); // null means no category filter
MixpanelManager().memoriesFiltered('all');
break;
}
});
}
MemoryCategory? category;
switch (option) {
case FilterOption.interesting:
category = MemoryCategory.interesting;
MixpanelManager().memoriesFiltered('interesting');
break;
case FilterOption.system:
category = MemoryCategory.system;
MixpanelManager().memoriesFiltered('system');
break;
case FilterOption.all:
category = null; // null means no category filter
MixpanelManager().memoriesFiltered('all');
break;
}

void _filterByCategory(MemoryCategory? category) {
if (!mounted) return;

setState(() {
_currentFilter = option;
_selectedCategory = category;
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To allow combining setState calls from different places (like in initState), you can modify this method to accept an optional callback. This callback can be executed inside the setState block, consolidating multiple state updates into one. This improves performance by reducing unnecessary rebuilds.

Additionally, the mounted check on line 211 is redundant since there's already a check on line 193 and no await operations are performed in between. The suggested change removes it.

  void _applyFilter(FilterOption option, {void Function()? andThen}) {
    if (!mounted) return;

    MemoryCategory? category;
    switch (option) {
      case FilterOption.interesting:
        category = MemoryCategory.interesting;
        MixpanelManager().memoriesFiltered('interesting');
        break;
      case FilterOption.system:
        category = MemoryCategory.system;
        MixpanelManager().memoriesFiltered('system');
        break;
      case FilterOption.all:
        category = null; // null means no category filter
        MixpanelManager().memoriesFiltered('all');
        break;
    }

    setState(() {
      _currentFilter = option;
      _selectedCategory = category;
      andThen?.call();
    });
  }

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.

FlutterError - MemoriesPageState._applyFilter

2 participants