-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix: null check operator used on a null value #3447
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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.
| _applyFilter(_currentFilter); | ||
|
|
||
| // Mark initial load as complete | ||
| if (mounted) { | ||
| setState(() { | ||
| _isInitialLoad = false; | ||
| }); | ||
| } | ||
| setState(() { | ||
| _isInitialLoad = false; | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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;
});| 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; | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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();
});
}
setStatewas called after the widget was already removedfix: Added mounted checks and moved provider updates outside of setState
closes #3442