Skip to content

Commit

Permalink
docs: OEP-67: ADR to use React Query over Redux, update JS/TS guidance (
Browse files Browse the repository at this point in the history
  • Loading branch information
bradenmacdonald authored Aug 15, 2024
1 parent 992db1e commit f012f27
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 33 deletions.
83 changes: 51 additions & 32 deletions oeps/best-practices/oep-0067-bp-tools-and-technology.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ OEP-67: Standard Tools and Technologies
* - Title
- Tools and Technology Standards
* - Last Modified
- 2023-09-05
- 2024-07-25
* - Authors
- Feanil Patel <[email protected]>
* - Arbiter
Expand Down Expand Up @@ -90,26 +90,30 @@ Frontend Technology Selection
users. This encompasses views rendered in Python on the server, interactive
interfaces written using JavaScript, and CSS styling.

.. _Use React and Redux:
.. _Use React:

#. **Use React**

**Rationale**: React must be used for building new UIs, as it is
widely adopted by the community and strikes a balance between
flexibility and feature richness.

When building in existing Django server-rendered pages, one can use the
react_render helper method to bridge to React. This bridge provides an
easy way to pass data into a React component from Django via props. For
more information about react_render see `ReactRender`_.
#. **Use React Query for data loading**

For loading data from the platform or other external sources (e.g. via REST
APIs), `React Query`_ should be used.

#. **Use Redux**
For client-side state management, regular React "state" and "context" should
be used alongside React Query, following the best practices described in the
official React docs: `Managing State`_.

For state management of complex
client-side interactions, Redux must be used. This library was chosen
because it sees strong use in the React community, but is also flexible
enough to be used in situations where a hybrid React/Backbone architecture
exists.
**Exception**: Much of our frontend code is currently written using Redux for
both data loading and state management, and that is also an accepted
approach. However, for new code or major refactorings of existing code, it is
recommended to use React Query and plain React state instead as described.

**Decision Record**: For details, see
:doc:`OEP-0067-0010 React Query <oep-0067/decisions/frontend/0010-react-query>`.

#. **Use Jest and React-Testing-Library to test React components**

Expand All @@ -122,20 +126,23 @@ Frontend Technology Selection

**Rationale**: edX JavaScript should be written consistent with the latest
ECMA-262 specification in order to ensure future support, the largest
community and the availability of modern features. Currently, the ECMA-262
edition 6 (ES6) is the edition with the largest support and should be used.
To support this syntax in older browsers, use `Babel`_. Babel may also be
configured to add syntax extensions widely adopted by the community of our
recommended framework (e.g., `JSX`_).
community and the availability of modern features. Currently, ES2022 is
the latest version with full compatibility from `the browsers we support`_.
There is no need to use Babel, core-js, nor polyfills to provide backwards
compatibility with unsupported browsers nor to transform ES2022 code into
ES6/ES5 code.

**TypeScript**: TypeScript should be utilized in frontend code wherever it
seems to provide value (especially in any code that is reused: libraries, API
wrappers, shared components, data type definitions, etc.). For details, see
:doc:`OEP-0067-0008 TypeScript <oep-0067/decisions/frontend/0008-typescript>`.

**Exception**: Much of edX's existing front end code is written conformant
to the edition of ECMA-262 released in 2009 (ES5). Files written in ES5
should be gradually converted to the newer standard as new development in
those feature areas requires.
**JSX**: Babel or other tooling may be used to add JSX syntax support to our
JavaScript/TypeScript code.

**Note**: edX previously used CoffeeScript, but its use has now been
deprecated. Community interest in TypeScript has also grown, but it and
other languages that do not follow the ECMA-262 spec should not be used.
**Porting**: Files written in ES5 and/or plain JS should be gradually
converted to the newer standard (e.g. TypeScript with ES2022 syntax) as new
development in those feature areas allows.

#. **JavaScript code should follow the edX ESLint configuration**

Expand Down Expand Up @@ -185,18 +192,18 @@ Frontend Technology Selection
implemented to handle as much of the "asset pipeline" as possible,
rather than passing this responsibility on to Django.

#. **JavaScript dependencies should be managed with ES2015 Modules**
#. **JavaScript dependencies should be managed with ES Modules**

**Rationale**: JavaScript module systems allow front end code to specify
its dependencies and be grouped into bundles that minimize the assets
needed to provide page functionality. The most prevalent module syntax
is currently `ES2015 Modules`_, which should be adopted everywhere
edX code is written to the ES2015 spec or later.
JavaScript/TypeScript code is used.

**Exception**: Much of edX's existing (ES5) JavaScript uses the older
**Exception**: Some of our existing JavaScript uses the older
`AMD Modules`_ syntax for modules. AMD Modules are interoperable
with ES2015 Modules if Webpack is used for bundling, so AMD is an
acceptable module definition if the code must remain ES5.
with ES2015 Modules if Webpack is used for bundling, so this is fine in
legacy code, but should not be used in new or refactored code.

#. **CSS should be generated using SCSS**

Expand All @@ -223,9 +230,11 @@ Frontend Technology Selection
#. **Server-side content should be rendered with Django Templates**

**Rationale**: Although it is advised to use client side templating with
React, see `Use React and Redux`_, when rendering on the server Django templates
should be used. There are many template languages available for Django,
but the simplest option is to use the built-in Django template engine.
React, see `Use React`_, in legacy code that generates HTML on the server,
Django templates should be used. There are many template languages available
for Django, but the simplest option is to use the built-in Django template
engine.

The Open edX codebase has a mixture of Django and Mako templates, but the
former are easier to reason about because they don't support arbitrary
code evaluation.
Expand Down Expand Up @@ -318,6 +327,13 @@ Consequences
Change History
**************

2024-07-25
==========

* Changed guidance on React state/data loading to recommend React Query instead of Redux
* Updated JavaScript/TypeScript guidance
* `Pull request #616 <https://github.com/openedx/open-edx-proposals/pull/616>`_

2023-09-05
==========

Expand All @@ -344,13 +360,16 @@ Change History
.. _Fetch: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
.. _Jest: https://jestjs.io/
.. _JSX: https://facebook.github.io/react/docs/introducing-jsx.html
.. _Managing State: https://react.dev/learn/managing-state
.. _oep 18: https://open-edx-proposals.readthedocs.io/en/latest/oep-0018-bp-python-dependencies.html
.. _package lock: https://docs.npmjs.com/cli/v6/configuring-npm/package-locks
.. _React: https://github.com/facebook/react
.. _React at edX: https://openedx.atlassian.net/wiki/display/FEDX/React
.. _React Query: https://tanstack.com/query/latest/docs/framework/react/overview
.. _React-Testing-Library: https://testing-library.com/docs/react-testing-library/intro
.. _ReactRender: https://github.com/openedx/edx-platform/blob/4b38b1f750918ff83c02cff776681aabe44bd689/common/djangoapps/pipeline_mako/templates/static_content.html#L159-L167
.. _Renovate: https://renovatebot.com/
.. _Sass documentation: http://sass-lang.com/
.. _the browsers we support: https://github.com/openedx/browserslist-config#supported-browsers
.. _Upgrade Automation How-to: https://docs.openedx.org/en/latest/developers/how-tos/enable-javascript-upgrade-automation.html
.. _Webpack: https://webpack.github.io/
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Use Redux
Status
******

Accepted
Replaced

(See :doc:`OEP-0067-0010 <0010-react-query>`)

Context
*******
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Use React Query
###############

Status
******

Accepted

Context
*******

The Open edX community needs a library to handle the common pattern of loading
data from the platform's REST APIs, as well as mutating data (submitting changes
using the API). Doing this properly and consistently requires consideration of
loading states, error handling, caching, cache invalidation, pagination, and
more.

A popular library for this purpose is
`React Query <https://tanstack.com/query/latest/docs/framework/react/overview>`_.

React Query provides a lot of useful functionality, including but not limited
to: consistent handling of loading and error states, automatic updates, caching,
cache invalidation, pagination, infinite scroll, request de-duplication,
optimistic updates, pre-fetching, compatibility with server side rendering, and
more. It does all this with a simple API, and requires a lot less boilerplate
than implementing the equivalent functionality using Redux [Toolkit].

Decision
********

For loading data from the platform or other external sources (e.g. via REST
APIs), `React Query <https://tanstack.com/query/latest/docs/framework/react/overview>`_
should be used.

For client-side state management, regular React "state" and "context" should be
used alongside React Query, following the best practices described in the
official React docs: `Managing State <https://react.dev/learn/managing-state>`_.

Consequence
***********

React Query has been adopted by the Open edX community as the library to use to
handle data loading, caching, and mutation in React applications.

Rejected Alternatives
*********************

1. **Redux**

Redux was previously recommended. At the time the original OEP was
written, React itself had poor state management capabilities and React Query
did not yet exist; the React community in general frequently recommended
Redux. However, now React itself has stronger state management (e.g. context)
and for data loading, React Query provides a lot more functionality and
simplicity compared to Redux.

0 comments on commit f012f27

Please sign in to comment.