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 State Mutation in Timeline Reducer and Refactor TimelineHandler for Immutable Week Title Updates #6144

Conversation

Abishekcs
Copy link
Contributor

@Abishekcs Abishekcs commented Jan 20, 2025

Note

Previously, I considered opening this as two separate PRs (#6138 and #6143). However, later i realized both require a common component change, specifically the TimelineHandler component.

For testing please set enableMutationChecks to true in create_store.js

What this PR does

  • Fixes state immutability issues in the weeks property of the timeline slice done by getWeeksArray selector.
  • Fixes mutation in timeline reducer(s) which are handling the action RESET_TITLES & UPDATE_TITLE

Cause of Bug (For getWeeksArray selector)

  • The bug lies in the direct modification of the newWeek object, which is a reference to the weeks property of the
    Redux state (Timeline Slice).

const newWeek = weeks[weekId];

Fix (For getWeeksArray selector)

  • Resolved by using spread operator since we are modifying only the top level properties of the object.

Cause of Bug (For RESET_TITLES & UPDATE_TITLE)

For this finding the cause of bug was easy as the error message exaclty indicated where mutation was as shown below:

For RESET_TITLES:

RESET_TITLES

For UPDATE_TITLE

UPDATE_TITLE

The spread operator doesn’t work as expected with deeply nested objects because it copies the values of the top-level properties of weeks to new addresses/references, but the inner objects retain the same addresses/references which are the one's updated by mutation.

Fix (For RESET_TITLES & UPDATE_TITLE)

Resolved by using Immer Produce.

Why the changes in TimelineHandler component?

Previously, the getWeeksArray selector was mutating the weeks property of the timeline slice directly. This meant that dispatching SAVED_TIMELINE from the saveTimeline function immediately after dispatching RESET_TITLES from the _resetTitles function worked without issues because both were referencing the same mutated weeks array from getWeeksArray selector.

So, after updating immutable way immediately dispatching won't work as the existing weeks in the TimlineHandler from selector doesn't have the same reference.

Little bit detail about redux for future reference:

  • In Redux:
    • Mutation: Changes are immediate since we were previously directly modifying the same object reference -
      any code holding that reference sees the changes instantly.
    • Immutable: Creates a new object reference, requiring React/Redux to process and batch the state update,
      making the changes not immediately available. Also, after resetting the timeline week titles, the saveTimeline
      was called immediately, leading to an API call right away. During this time, Redux had not yet received the
      new updates.
    • Source: Immutability in React and Redux: The Complete Guide

Screenshots (For getWeeksArray selector)

Before:

Before.mp4

After:

After.mp4

Screenshots (For RESET_TITLES & UPDATE_TITLE)

Before:

Before.mp4

After:

After.mp4

@Abishekcs
Copy link
Contributor Author

@ragesoss would you be open to using Immer for immutability updates? Redux Toolkit has Immer built-in, but we'd need to refactor our reducer file to use it.

@ragesoss
Copy link
Member

@Abishekcs sure, seems reasonable.

@Abishekcs Abishekcs force-pushed the fix/timeline-state-immutability branch from 44ba6da to 8e6a3a2 Compare January 22, 2025 10:27
@Abishekcs Abishekcs marked this pull request as ready for review January 22, 2025 10:54
@ragesoss
Copy link
Member

This seems fine to me, but since it's introducing a new tool, the PR should probably include some explanation of it in frontend.md.

Also, as part of the PR description, please note how adding this package affect the bundle size.

@@ -6866,7 +6867,7 @@ __metadata:
languageName: node
linkType: hard

"immer@npm:^10.0.3":
"immer@npm:^10.0.3, immer@npm:^10.1.1":
Copy link
Member

Choose a reason for hiding this comment

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

Since it looks like we're already using a different version of immer, is it possible to just use the newer version without the older one (possibly by upgrading whatever dependency was already requiring it)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ragesoss i think both version ranges (^10.0.3 and ^10.1.1) are being satisfied by a single installation of version 10.1.1. as shown in yarn .

version: 10.1.1

So there's only one version installed, and it satisfies both requirements.
And, while installing Redux Toolkit (RTK) in PR #5867 , it brought in immer as a dependency since RTK uses immer internally for its immutable state updates.

Copy link
Member

Choose a reason for hiding this comment

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

Great. So it shouldn't affect the bundle size either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great. So it shouldn't affect the bundle size either.

Yes.

@Abishekcs
Copy link
Contributor Author

This seems fine to me, but since it's introducing a new tool, the PR should probably include some explanation of it in frontend.md.

Also, as part of the PR description, please note how adding this package affect the bundle size.

Okay

@Abishekcs Abishekcs marked this pull request as draft January 27, 2025 18:34
@Abishekcs Abishekcs marked this pull request as ready for review January 27, 2025 18:36
@Abishekcs Abishekcs marked this pull request as draft January 27, 2025 18:37
@Abishekcs Abishekcs force-pushed the fix/timeline-state-immutability branch from 8e6a3a2 to 55c4061 Compare January 27, 2025 19:00
@Abishekcs
Copy link
Contributor Author

Abishekcs commented Jan 27, 2025

@ragesoss i have updated the frontend.md.

a) There, is one link i.e Thinking in React which leads to page not found.
b) Also, the doc needs to be updated to reflect the recent changes in react and redux. I will make those changes in seperate PR related only to the docs.

@Abishekcs Abishekcs marked this pull request as ready for review January 27, 2025 19:04
@ragesoss
Copy link
Member

Thanks! This looks good to me; I'll merge once the tests pass.

@ragesoss ragesoss merged commit 581e5fe into WikiEducationFoundation:master Jan 27, 2025
1 check passed
@Abishekcs Abishekcs deleted the fix/timeline-state-immutability branch January 27, 2025 20:44
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.

2 participants