openedx / openedx/frontend-app-learning

Convert Learning from redux to Context + react-query

Open
#1,946 6 comments 0 reactions 2 assignees View on GitHub

@arbrandes is already working on this.

Since Aug 20, 2026.

Dominant language
JavaScript
Stars
70
Forks
335
Avg merge
1d 17h
Merged PRs (30d)
35

Description

[!NOTE]
This issue body was generated by Claude (Claude Code) and reviewed before posting.

Summary

Convert frontend-app-learning from Redux to React Query (for server state) + React state/context (for client state), on master. This is Stage 1 of 2 on the road to frontend-base: the frontend-base port (#1905) is blocked on this work, because the frontend-base shell provides a global React Query client and does not carry Redux.

Why

  • OEP-0067 ADR-0010 mandates React Query for server state and plain React state/context for client state; the older Redux ADR is superseded.
  • The frontend-base migration guide is explicit: "If the MFE uses Redux, consider porting the app over to react-query, as it will make it much easier to handle header (and footer) customization."
  • Doing the Redux removal first (on master) keeps it decoupled from the toolchain swap, matching how the reference apps sequenced it.

Reference conversions

Part of the org-wide effort tracked in openedx/public-engineering#450. Both reference apps converted on master first, then forward-ported to their frontend-base branch:

  • learner-dashboard #786 "React query and react context conversion" (later forward-ported in #801).
  • authn #1629 "React query migration" (later forward-ported in #1641).

Scope

Learning currently has 7 store reducers, 5 local slices (~40 hand-written thunks), generic/model-store as the central normalized cache, ~104 useSelector / ~58 useDispatch sites, and only 2 connect() components. injectIntl → useIntl is already done.

The work breaks down per feature area — see the sub-issues. Test-infrastructure migration (off axios-mock-adapter / initializeTestStore, reusing Rosie factories + Pact tests) happens within each item as its own tests convert, not as a separate task.

The plugins Redux slice (generic/plugin-store, a bespoke override-method registry) is in scope here — its de-Redux is tracked in #2017. Don't confuse it with the separate @openedx/frontend-plugin-framework → frontend-base Slot migration, which is part of the Stage-2 frontend-base port (#1905).

Known blocker: @edx/frontend-lib-special-exams

@edx/frontend-lib-special-exams (^4.0.0) is itself Redux-based: it exports the specialExams reducer that learning registers in store.ts, and its components (OuterExamTimer, SequenceExamWrapper) and exam-access hooks read that slice via react-redux. Learning never touches state.specialExams itself (its own exam data lives in courseHome.examsData), so this is purely an infrastructure coupling.

What is and isn't blocked. Learning's own internal conversion — including reducing the store to specialExams-only (#1978) — is not blocked by the library; it depends only on learning's remaining Stage-1 work. What waits on the library is the final step: dropping react-redux / redux / @reduxjs/toolkit from learning's package.json (and deleting store.ts / AppProvider store=), because those exam components need a react-redux Provider + store somewhere above them, and frontend-base's SiteProvider supplies neither.

The required library change is not necessarily a full React Query rewrite. Two options: (A) make the library self-contained — it ships its own store and wraps its exported components in their own Provider, so consumers register nothing (redux becomes transitive-only for consumers); or (B) convert the library to React Query. These are being evaluated in #2018 before any decision; nothing is filed on frontend-lib-special-exams until that investigation settles on a concrete approach.

The full phase-by-phase plan is in the first comment below; a progress review + the courseware decomposition are in a later comment.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.