Skip to content

Fix loading race conditions#1667

Merged
nygrenh merged 2 commits intomasterfrom
fix-stuff
Mar 6, 2026
Merged

Fix loading race conditions#1667
nygrenh merged 2 commits intomasterfrom
fix-stuff

Conversation

@nygrenh
Copy link
Member

@nygrenh nygrenh commented Mar 6, 2026

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved error handling and user feedback when exercises fail to load with clearer error messages and a retry option.
  • New Features

    • Added "Try again" button to allow users to retry failed exercise loads.
  • Localization

    • Added new localized error messages for exercise loading failures and retry button text.

nygrenh added 2 commits March 6, 2026 08:32
…setting organizationSlug and viewParams. This change improves state management and simplifies the component's logic.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

Refactored atom hydration to use explicit setters with effects in ExamPageShell, improved loading and error state handling in exercise components by decoupling them with separate early returns, and added localized error messages and retry button text to translation files.

Changes

Cohort / File(s) Summary
Atom State Management
services/main-frontend/src/app/org/[organizationSlug]/(course-material)/exams/ExamPageShell.tsx
Replaced useHydrateAtoms with explicit useSetAtom calls within a useEffect to synchronize atom values with component props, shifting from render-time hydration to effect-based prop propagation.
Exercise Component Loading & Error Handling
services/main-frontend/src/components/course-material/ContentRenderer/moocfi/ExerciseBlock/PeerOrSelfReviewViewImpl.tsx, services/main-frontend/src/components/course-material/ContentRenderer/moocfi/ExerciseBlock/index.tsx
Split combined loading/missing-data condition into separate early returns: loading state shows spinner, missing data shows error banner with retry. Tightened loading guard logic and added explicit error UI feedback.
Localization Updates
shared-module/packages/common/src/locales/en/main-frontend.json, shared-module/packages/common/src/locales/en/shared-module.json
Added translation keys for retry button text (button-text-try-again) and exercise load error message (error-loading-exercise); reorganized hydration/fallback-related translation keys in shared-module locale.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

bug, refactor

Poem

A rabbit refactors with care,
Atoms now sync through the air,
Loading states split, errors show clear,
"Try again!" when troubles appear,
Better flows, less despair! 🐰

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Fix loading race conditions' directly addresses the primary changes: refactoring loading state handling, synchronizing prop values to atoms via effects, and improving error handling for loading scenarios across multiple components.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-stuff

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 added bug Something isn't working refactor labels Mar 6, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@services/main-frontend/src/components/course-material/ContentRenderer/moocfi/ExerciseBlock/index.tsx`:
- Around line 305-325: Replace the use of React Query's isLoading with
isFetching in the render gating for getCourseMaterialExercise so the Spinner
(Spinner component) shows during refetches triggered by
getCourseMaterialExercise.refetch(); specifically, change checks that reference
getCourseMaterialExercise.isLoading to use getCourseMaterialExercise.isFetching
(and keep the existing ErrorBanner + retry button behavior) so clicking the
retry button gives a visual loading indicator while the fetch is in progress.

In `@shared-module/packages/common/src/locales/en/shared-module.json`:
- Line 40: These translation keys ("dynamic-loading-cause-hydration-script",
"dynamic-loading-cause-runtime-error", "dynamic-loading-cause-suspense-forever",
"dynamic-loading-possible-causes-title") are not referenced anywhere (only
"dynamic-loading-fallback-title" and "dynamic-loading-fallback-reason" are used
in DynamicImportFallback.tsx); either remove these unused keys from
shared-module.json to avoid dead translations or keep them but add a short TODO
comment in the PR description and a code comment near DynamicImportFallback.tsx
indicating planned usage (and list the exact keys) so reviewers know they’re
intentionally reserved for a future implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a61429a0-27e7-4887-bb98-bff25d864dbc

📥 Commits

Reviewing files that changed from the base of the PR and between 9b13fff and f7ff1af.

📒 Files selected for processing (5)
  • services/main-frontend/src/app/org/[organizationSlug]/(course-material)/exams/ExamPageShell.tsx
  • services/main-frontend/src/components/course-material/ContentRenderer/moocfi/ExerciseBlock/PeerOrSelfReviewView/PeerOrSelfReviewViewImpl.tsx
  • services/main-frontend/src/components/course-material/ContentRenderer/moocfi/ExerciseBlock/index.tsx
  • shared-module/packages/common/src/locales/en/main-frontend.json
  • shared-module/packages/common/src/locales/en/shared-module.json

Comment on lines +305 to +325
if (getCourseMaterialExercise.isLoading) {
return <Spinner variant={"medium"} />
}
if (!getCourseMaterialExercise.data) {
return (
<div>
<ErrorBanner
variant={"readOnly"}
error={t("error-loading-exercise", { defaultValue: "Error loading exercise" })}
/>
<button
className={cx(exerciseButtonStyles)}
onClick={() => {
void getCourseMaterialExercise.refetch()
}}
>
{t("button-text-try-again", { defaultValue: "Try again" })}
</button>
</div>
)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use isFetching instead of isLoading for consistent refetch feedback.

When the user clicks the Retry button, refetch() is called. However, React Query's isLoading is only true during the initial load, not during refetches—only isFetching becomes true during refetch operations. This means the spinner won't display while the retry is in progress, leaving users without visual feedback.

This is inconsistent with PeerOrSelfReviewViewImpl.tsx (lines 195-197 in context snippet 2), which correctly uses isFetching with an explicit comment explaining: "Uses isFetching instead of isPending because we want there to be a visual indication when the refresh button is clicked".

Proposed fix
-  if (getCourseMaterialExercise.isLoading) {
+  if (getCourseMaterialExercise.isFetching) {
     return <Spinner variant={"medium"} />
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (getCourseMaterialExercise.isLoading) {
return <Spinner variant={"medium"} />
}
if (!getCourseMaterialExercise.data) {
return (
<div>
<ErrorBanner
variant={"readOnly"}
error={t("error-loading-exercise", { defaultValue: "Error loading exercise" })}
/>
<button
className={cx(exerciseButtonStyles)}
onClick={() => {
void getCourseMaterialExercise.refetch()
}}
>
{t("button-text-try-again", { defaultValue: "Try again" })}
</button>
</div>
)
}
if (getCourseMaterialExercise.isFetching) {
return <Spinner variant={"medium"} />
}
if (!getCourseMaterialExercise.data) {
return (
<div>
<ErrorBanner
variant={"readOnly"}
error={t("error-loading-exercise", { defaultValue: "Error loading exercise" })}
/>
<button
className={cx(exerciseButtonStyles)}
onClick={() => {
void getCourseMaterialExercise.refetch()
}}
>
{t("button-text-try-again", { defaultValue: "Try again" })}
</button>
</div>
)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@services/main-frontend/src/components/course-material/ContentRenderer/moocfi/ExerciseBlock/index.tsx`
around lines 305 - 325, Replace the use of React Query's isLoading with
isFetching in the render gating for getCourseMaterialExercise so the Spinner
(Spinner component) shows during refetches triggered by
getCourseMaterialExercise.refetch(); specifically, change checks that reference
getCourseMaterialExercise.isLoading to use getCourseMaterialExercise.isFetching
(and keep the existing ErrorBanner + retry button behavior) so clicking the
retry button gives a visual loading indicator while the fetch is in progress.

@nygrenh nygrenh merged commit b231cb6 into master Mar 6, 2026
16 checks passed
@nygrenh nygrenh deleted the fix-stuff branch March 6, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant