Skip to content

fix: persist visualization state across module navigation (#653)#683

Open
BekkamMallishwari wants to merge 1 commit into
algoscope-hq:mainfrom
BekkamMallishwari:fix/visualization-state-persistence-653
Open

fix: persist visualization state across module navigation (#653)#683
BekkamMallishwari wants to merge 1 commit into
algoscope-hq:mainfrom
BekkamMallishwari:fix/visualization-state-persistence-653

Conversation

@BekkamMallishwari

@BekkamMallishwari BekkamMallishwari commented Jun 19, 2026

Copy link
Copy Markdown

Related Issue

Closes #653

Summary

Fixed an issue where visualization progress was lost when users navigated between algorithm modules.

Changes Made

  • Added visualization state persistence
  • Preserved animation progress
  • Preserved selected algorithm settings
  • Improved user experience during module navigation

Testing

  • Tested navigation between modules
  • Verified state restoration
  • Verified build and lint checks

Summary by CodeRabbit

  • New Features

    • Visualization settings (algorithm selection, speed, custom inputs) and playback state are now persisted across navigations.
  • Refactor

    • Algorithm visualizers updated to use a unified state management system for improved consistency.

@netlify

netlify Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploy Preview for astounding-nougat-da0f6a ready!

Name Link
🔨 Latest commit b18792d
🔍 Latest deploy log https://app.netlify.com/projects/astounding-nougat-da0f6a/deploys/6a34b034ec39ac000800a78f
😎 Deploy Preview https://deploy-preview-683--astounding-nougat-da0f6a.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the adityapaul2603-gmailcom's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new React context system (VisualizationStateContext, VisualizationStateProvider, useVisualizationState) backed by a useRef Map is introduced to persist visualization UI and playback state across navigation. useStepPlayback gains initialState/onStateChange parameters. Five algorithm visualizer components migrate from local useState to this shared store.

Changes

Shared Visualization State Persistence

Layer / File(s) Summary
Context, provider, and hook
src/context/visualizationStateContext.js, src/context/visualizationState.jsx, src/context/useVisualizationState.js
Defines VisualizationStateContext (null default), implements VisualizationStateProvider using a useRef-backed Map with lazy getState and functional-update setState, and creates useVisualizationState(key, initialValue) that syncs local state with the context store.
App root wiring
src/main.jsx
Imports VisualizationStateProvider and wraps App in both the Clerk-authenticated and unauthenticated render branches.
useStepPlayback: initialState and onStateChange
src/components/visualizer/useStepPlayback.js
Adds DEFAULT_PLAYBACK_STATE, expands hook signature to accept initialState (seeds steps/currentStepIndex/isPlaying) and an optional onStateChange callback fired via effect when those values change.
Sorting visualizer migration
src/components/sortingAlgo/Visualizer.jsx
Replaces all local useState with useVisualizationState under SORTING_STATE_KEY; adds URL-param/persisted-algorithm fallback useEffect; reconfigures useStepPlayback with persisted playback; updates handleReset, algorithm-change, and category-change handlers to write/clear persisted state.
Array search visualizer migration
src/components/arraySearch/Visualizer.jsx
Defines ARRAY_SEARCH_STATE_KEY, replaces eight useState calls with useVisualizationState, and wires useStepPlayback with initialState/onStateChange.
Greedy algo visualizer migration
src/components/greedyAlgo/VisualizerPage.jsx
Introduces GREEDY_STATE_KEY, migrates all settings and playbackState to useVisualizationState, and updates useStepPlayback to round-trip playback state through the store.
Kadane, Moore Voting, and Graph Search migrations
src/components/kadaneAlgo/VisualizerPage.jsx, src/components/mooreVotingAlgo/VisualizerPage.jsx, src/components/searchAlgo/VisualizerPage.jsx
Kadane and Moore Voting each swap four useState hooks for useVisualizationState; Graph Search migrates six fields and updates the handleGraphChange dependency array.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(100, 180, 255, 0.5)
    Note over User,Store: First visit to Sorting Visualizer
    User->>SortingVisualizer: open /sorting?algo=bubble
    SortingVisualizer->>useVisualizationState: getState("sorting:solo:algorithm", "bubble")
    useVisualizationState->>Store: Map.get → null, init "bubble"
    Store-->>SortingVisualizer: "bubble"
    User->>SortingVisualizer: play animation
    SortingVisualizer->>useStepPlayback: { speed, initialState, onStateChange }
    useStepPlayback-->>Store: onStateChange({ steps, currentStepIndex, isPlaying })
  end

  rect rgba(100, 220, 140, 0.5)
    Note over User,Store: Navigate away and return
    User->>Router: navigate to /graph-search
    User->>Router: navigate back to /sorting
    SortingVisualizer->>useVisualizationState: getState("sorting:solo:algorithm")
    useVisualizationState->>Store: Map.get → "bubble" (persisted)
    Store-->>SortingVisualizer: "bubble" + prior playback state
    SortingVisualizer->>useStepPlayback: initialState = persisted playbackState
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • algoscope-hq/AlgoScope#309: Modifies the same arraySearch/Visualizer.jsx and sortingAlgo/Visualizer.jsx components, directly intersecting with this PR's state/playback wiring changes.
  • algoscope-hq/AlgoScope#680: Removes greedyAlgo/VisualizerPage.jsx and greedy-related modules, creating a direct conflict with this PR's migration of that same file to useVisualizationState.

Suggested labels

type:bug, level:intermediate

Suggested reviewers

  • Bimbok
🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive Description provides the essential summary and context but lacks the structured PR template with type selection, testing verification, and release notes sections. Complete the PR template by selecting a change type (fix), testing verification steps, and specifying the release notes category and entry for consistency.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing visualization state persistence across module navigation, addressing the core issue.
Linked Issues check ✅ Passed The PR fully implements the solution requested in #653: adds visualization state persistence via Context API, preserves animation progress and algorithm settings across module navigation.
Out of Scope Changes check ✅ Passed All changes directly address #653 by introducing the persistence layer (VisualizationStateProvider, useVisualizationState, useStepPlayback updates) and integrating it into visualizer components.
Algorithm Complexity ✅ Passed PR is not applicable to this check: it adds state persistence for visualization UI, not algorithm implementations. No algorithmic logic or complexity documentation is involved.
Conventional Commits ✅ Passed Commit message "fix: persist visualization state across module navigation (#653)" properly follows conventional commit standards with correct type (fix), separator, and description.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/visualization-state-persistence-653

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/components/visualizer/useStepPlayback.js (1)

38-40: 🏗️ Heavy lift

Avoid per-tick persistence writes to reduce render churn.

This effect runs every step transition and pushes state outward each time. With onStateChange wired to React state, that can add extra renders during animations.

As per coding guidelines, "Focus on React best practices, avoiding unnecessary re-renders, and efficient state management."

One practical direction
-  useEffect(() => {
-    onStateChange?.({ steps, currentStepIndex, isPlaying })
-  }, [currentStepIndex, isPlaying, onStateChange, steps])
+  const lastEmittedRef = useRef(null)
+  useEffect(() => {
+    if (!onStateChange) return
+    const next = { steps, currentStepIndex, isPlaying }
+    const prev = lastEmittedRef.current
+    if (
+      prev &&
+      prev.steps === next.steps &&
+      prev.currentStepIndex === next.currentStepIndex &&
+      prev.isPlaying === next.isPlaying
+    ) {
+      return
+    }
+    lastEmittedRef.current = next
+    onStateChange(next)
+  }, [steps, currentStepIndex, isPlaying, onStateChange])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/visualizer/useStepPlayback.js` around lines 38 - 40, The
useEffect hook in the useStepPlayback component is calling onStateChange on
every change to currentStepIndex or isPlaying, which triggers parent component
re-renders during each animation tick. To fix this, memoize the onStateChange
callback using useCallback in the parent component (where onStateChange is
defined) to prevent unnecessary re-renders, and consider debouncing or
throttling the onStateChange calls in the useEffect to batch updates together
instead of firing on every single tick transition. This will decouple the step
transitions from immediate state propagation and reduce render churn during
animations.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/context/useVisualizationState.js`:
- Around line 13-27: The `useState` initialization in the hook only reads from
`context.getState(key, initialValue)` once during mount, so if the `key` prop
changes, the state will continue reading from the old key while
`setPersistentState` writes to the new key, causing a mismatch. Add a
`useEffect` hook with `key` in the dependency array that calls `setLocalState`
with `context.getState(key, initialValue)` whenever `key` changes, ensuring
reads and writes are always synchronized to the current key.

---

Nitpick comments:
In `@src/components/visualizer/useStepPlayback.js`:
- Around line 38-40: The useEffect hook in the useStepPlayback component is
calling onStateChange on every change to currentStepIndex or isPlaying, which
triggers parent component re-renders during each animation tick. To fix this,
memoize the onStateChange callback using useCallback in the parent component
(where onStateChange is defined) to prevent unnecessary re-renders, and consider
debouncing or throttling the onStateChange calls in the useEffect to batch
updates together instead of firing on every single tick transition. This will
decouple the step transitions from immediate state propagation and reduce render
churn during animations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: be869d5f-ba2d-430c-8587-eab7737a9a35

📥 Commits

Reviewing files that changed from the base of the PR and between 0974299 and b18792d.

📒 Files selected for processing (11)
  • src/components/arraySearch/Visualizer.jsx
  • src/components/greedyAlgo/VisualizerPage.jsx
  • src/components/kadaneAlgo/VisualizerPage.jsx
  • src/components/mooreVotingAlgo/VisualizerPage.jsx
  • src/components/searchAlgo/VisualizerPage.jsx
  • src/components/sortingAlgo/Visualizer.jsx
  • src/components/visualizer/useStepPlayback.js
  • src/context/useVisualizationState.js
  • src/context/visualizationState.jsx
  • src/context/visualizationStateContext.js
  • src/main.jsx

Comment thread src/context/useVisualizationState.js
@BekkamMallishwari

Copy link
Copy Markdown
Author

Hi @algoscope-hq team,

I have fixed Issue #653 and submitted this PR for review. The visualization state now persists across module navigation, preventing users from losing their progress.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Visualization state resets when navigating between modules

2 participants