-
Notifications
You must be signed in to change notification settings - Fork 251
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) O3-4382: Fixing the reset button functionality #2217
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.
Thanks for taking a stab at this, @UNCANNY69. While the memoization suggestion helps, the core issue appears to be deeper within the FilterContext
flow. The RESET_TREE
action in the FilterContext
reducer fires correctly but fails to clear the checkboxes. There seems to be an issue with the FilterProvider
state initialization that prevents re-initialization when the roots change.
To test this hypothesis out, try adding this force reset to FilterProvider
that fires when roots
changes:
useEffect(() => {
dispatch({ type: ReducerActionType.RESET_TREE });
}, [roots]);
You'll see that this resets the filters. There's still some exploration to be done, but I think it's better to focus there for the moment.
@@ -24,12 +24,12 @@ const TreeViewWrapper: React.FC<TreeViewWrapperProps> = (props) => { | |||
const { roots, isLoading, error } = useGetManyObstreeData(conceptUuids); | |||
|
|||
if (error) return <ErrorState error={error} headerTitle={t('dataLoadError', 'Data load error')} />; | |||
|
|||
const MemoizedFilterProvider = React.memo(FilterProvider); |
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.
Because MemoizedFilterProvider
is declared within the TreeViewWrapper
component:
- A new component type is created on every render of
TreeViewWrapper
- React will unmount the older provider and mount a new one each time
TreeViewWrapper
re-renders - Any state in the subtree of
FilterProvider
will reset on re-render
We should move the memoized component outside the parent to preserve its identity as a stable reference:
const MemoizedFilterProvider = React.memo(FilterProvider);
const TreeViewWrapper: React.FC<TreeViewWrapperProps> = (props) => {
// ... rest of the code
return <MemoizedFilterProvider roots={...} />;
};
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.
I realised that the solution work in a completely unexpected way (Due to it referencing the component again its remounting and triggering initialize action , which is completely not right)
This is 100% right, this behaviour is not the right flow but this is a better solution then the one I mentioned above, will look into how I can prevent this. The roots reference is changing i will se the way to prevent that |
@denniskigen I made the roots stable , thus this code below stopped working but the
can I try to change the location of the reset button of move the state to an upper level? |
Requirements
Summary
In the initial implementation, the FilterProvider component was being re-created whenever the parent component (TreeViewWrapper) re-rendered. This caused the state within the FilterProvider to reset, even when no changes were made to its inputs. The observed flow of console.log statements showed that the FilterProvider was being re-rendered unnecessarily, leading to unintended side effects like resetting the checkbox values stored in the filter state.
The root cause was that the FilterProvider component's re-creation was linked to the lifecycle of TreeViewWrapper, which was itself re-rendering due to changes in its own state or props.
Solution:
Initially it led me to think roots were needed to be memoized the roots , but for the life of me I am not sure why it did not work thus I used React.memo as it memoizes the rendered output of the FilterProvider and skips re-renders unless its props change. By memoizing it, the FilterProvider remains the same instance across renders unless the roots prop is updated.
Screenshots
OpenMRS.-.Brave.2025-01-29.02-32-21.mp4
Related Issue
Other