From d1f038cdcdb4b991d945ff90ca6103bcd44716a5 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 11 Mar 2026 13:55:06 -0400 Subject: [PATCH 1/2] support react 19 --- dash/_dash_renderer.py | 44 ++++++++++++++++++++++++++----- dash/dash-renderer/init.template | 40 +++++++++++++++++++++++++--- dash/development/build_process.py | 16 +++++++++-- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/dash/_dash_renderer.py b/dash/_dash_renderer.py index ee507ddb71..a9fcc68b0f 100644 --- a/dash/_dash_renderer.py +++ b/dash/_dash_renderer.py @@ -3,8 +3,8 @@ __version__ = "3.0.0" -_available_react_versions = {"18.3.1", "18.2.0", "16.14.0"} -_available_reactdom_versions = {"18.3.1", "18.2.0", "16.14.0"} +_available_react_versions = {"18.3.1", "18.2.0", "19.2.0"} +_available_reactdom_versions = {"18.3.1", "18.2.0", "19.2.0"} _js_dist_dependencies: List[Dict[str, Any]] = [] # to be set by _set_react_version @@ -19,19 +19,51 @@ def _set_react_version(v_react, v_reactdom=None): assert v_react in _available_react_versions, react_err assert v_reactdom in _available_reactdom_versions, reactdom_err + # React 19+ removed UMD builds, use umd-react package instead + is_react19 = v_react.startswith("19.") + is_reactdom19 = v_reactdom.startswith("19.") + + if is_react19: + react_prod_url = ( + f"https://unpkg.com/umd-react@{v_react}/dist/react.production.min.js" + ) + react_dev_url = ( + f"https://unpkg.com/umd-react@{v_react}/dist/react.development.js" + ) + else: + react_prod_url = ( + f"https://unpkg.com/react@{v_react}/umd/react.production.min.js" + ) + react_dev_url = f"https://unpkg.com/react@{v_react}/umd/react.development.js" + + if is_reactdom19: + reactdom_prod_url = ( + f"https://unpkg.com/umd-react@{v_reactdom}/dist/react-dom.production.min.js" + ) + reactdom_dev_url = ( + f"https://unpkg.com/umd-react@{v_reactdom}/dist/react-dom.development.js" + ) + else: + reactdom_prod_url = ( + f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.production.min.js" + ) + reactdom_dev_url = ( + f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.development.js" + ) + _js_dist_dependencies[:] = [ { "external_url": { "prod": [ "https://unpkg.com/@babel/polyfill@7.12.1/dist/polyfill.min.js", - f"https://unpkg.com/react@{v_react}/umd/react.production.min.js", - f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.production.min.js", + react_prod_url, + reactdom_prod_url, "https://unpkg.com/prop-types@15.8.1/prop-types.min.js", ], "dev": [ "https://unpkg.com/@babel/polyfill@7.12.1/dist/polyfill.min.js", - f"https://unpkg.com/react@{v_react}/umd/react.development.js", - f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.development.js", + react_dev_url, + reactdom_dev_url, "https://unpkg.com/prop-types@15.8.1/prop-types.js", ], }, diff --git a/dash/dash-renderer/init.template b/dash/dash-renderer/init.template index 463cfa02aa..12119dea23 100644 --- a/dash/dash-renderer/init.template +++ b/dash/dash-renderer/init.template @@ -19,19 +19,51 @@ def _set_react_version(v_react, v_reactdom=None): assert v_react in _available_react_versions, react_err assert v_reactdom in _available_reactdom_versions, reactdom_err + # React 19+ removed UMD builds, use umd-react package instead + is_react19 = v_react.startswith("19.") + is_reactdom19 = v_reactdom.startswith("19.") + + if is_react19: + react_prod_url = ( + f"https://unpkg.com/umd-react@{v_react}/dist/react.production.min.js" + ) + react_dev_url = ( + f"https://unpkg.com/umd-react@{v_react}/dist/react.development.js" + ) + else: + react_prod_url = ( + f"https://unpkg.com/react@{v_react}/umd/react.production.min.js" + ) + react_dev_url = f"https://unpkg.com/react@{v_react}/umd/react.development.js" + + if is_reactdom19: + reactdom_prod_url = ( + f"https://unpkg.com/umd-react@{v_reactdom}/dist/react-dom.production.min.js" + ) + reactdom_dev_url = ( + f"https://unpkg.com/umd-react@{v_reactdom}/dist/react-dom.development.js" + ) + else: + reactdom_prod_url = ( + f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.production.min.js" + ) + reactdom_dev_url = ( + f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.development.js" + ) + _js_dist_dependencies[:] = [ { "external_url": { "prod": [ "https://unpkg.com/@babel/polyfill@$polyfill/dist/polyfill.min.js", - f"https://unpkg.com/react@{v_react}/umd/react.production.min.js", - f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.production.min.js", + react_prod_url, + reactdom_prod_url, "https://unpkg.com/prop-types@$proptypes/prop-types.min.js", ], "dev": [ "https://unpkg.com/@babel/polyfill@$polyfill/dist/polyfill.min.js", - f"https://unpkg.com/react@{v_react}/umd/react.development.js", - f"https://unpkg.com/react-dom@{v_reactdom}/umd/react-dom.development.js", + react_dev_url, + reactdom_dev_url, "https://unpkg.com/prop-types@$proptypes/prop-types.js", ], }, diff --git a/dash/development/build_process.py b/dash/development/build_process.py index be65553716..81c184ebca 100644 --- a/dash/development/build_process.py +++ b/dash/development/build_process.py @@ -143,7 +143,19 @@ def bundles(self, build=None): # pylint:disable=too-many-locals versions[f"extra_{name_squashed}_versions"] = f'"{extras_str}"' for extra_version in extras: - url = f"https://unpkg.com/{name}@{extra_version}/umd/{filename}" + # React 19+ removed UMD builds, use umd-react package instead + if name in ("react", "react-dom") and extra_version.startswith("19."): + # Map filename to umd-react dist path + if "production.min" in filename: + umd_filename = f"{name}.production.min.js" + elif "development" in filename: + umd_filename = f"{name}.development.js" + else: + umd_filename = filename + url = f"https://unpkg.com/umd-react@{extra_version}/dist/{umd_filename}" + else: + url = f"https://unpkg.com/{name}@{extra_version}/umd/{filename}" + res = requests.get(url) extra_target = f"{name}@{extra_version}.{ext}" extra_path = self._concat(self.deps_folder, extra_target) @@ -169,7 +181,7 @@ def __init__(self): """dash-renderer's path is binding with the dash folder hierarchy.""" extras = [ "18.2.0", - "16.14.0", + "19.2.0", ] # versions to include beyond what's in package.json super().__init__( self._concat(os.path.dirname(__file__), os.pardir, "dash-renderer"), From de0a519281b0766406c2be64ee1f5bd2499d3de4 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 11 Mar 2026 14:18:10 -0400 Subject: [PATCH 2/2] fix lintstaged for python subdirectory files --- .lintstagedrc.js | 2 +- dash/development/build_process.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.lintstagedrc.js b/.lintstagedrc.js index e4449e59cd..c60351d080 100644 --- a/.lintstagedrc.js +++ b/.lintstagedrc.js @@ -26,7 +26,7 @@ const sh_cd = (directory, command) => { module.exports = { // Python checks (run from root, using root venv) - "dash/*.py": (filenames) => [ + "dash/**/*.py": (filenames) => [ `${venvBin("python")} -m pylint --rcfile=.pylintrc ${filenames.join( " " )}`, diff --git a/dash/development/build_process.py b/dash/development/build_process.py index 81c184ebca..01c9a01086 100644 --- a/dash/development/build_process.py +++ b/dash/development/build_process.py @@ -144,7 +144,9 @@ def bundles(self, build=None): # pylint:disable=too-many-locals for extra_version in extras: # React 19+ removed UMD builds, use umd-react package instead - if name in ("react", "react-dom") and extra_version.startswith("19."): + if name in ("react", "react-dom") and extra_version.startswith( + "19." + ): # Map filename to umd-react dist path if "production.min" in filename: umd_filename = f"{name}.production.min.js"