{"componentChunkName":"component---src-templates-post-template-js","path":"/en-US/ecosystem/react19","result":{"data":{"current":{"frontmatter":{"title":"React 19 Adaptation","order":3,"brief":"React 19 adaptation guide","icon":"doc-configprovider"},"fields":{"type":"ecosystem"},"tableOfContents":{"items":[{"url":"#whats-special-about-react-19","title":"What's Special About React 19","items":[{"url":"#1-reactdomrender-removed","title":"1. ReactDOM.render Removed"},{"url":"#2-reactdomfinddomnode-removed","title":"2. ReactDOM.findDOMNode Removed"},{"url":"#why-do-we-need-an-adapter","title":"Why Do We Need an Adapter"}]},{"url":"#quick-start","title":"Quick Start","items":[{"url":"#installation","title":"Installation"},{"url":"#react-19-users-important","title":"React 19 Users (Important)"},{"url":"#react-161718-users","title":"React 16/17/18 Users"}]},{"url":"#notes","title":"Notes","items":[{"url":"#tooltip-and-class-component-limitations","title":"Tooltip and Class Component Limitations"},{"url":"#error-messages","title":"Error Messages"}]},{"url":"#faq","title":"FAQ"},{"url":"#technical-details","title":"Technical Details","items":[{"url":"#version-compatibility-matrix","title":"Version Compatibility Matrix"},{"url":"#how-the-adapter-works","title":"How the Adapter Works"}]}]},"body":"var _excluded = [\"components\"];\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }\nfunction _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }\n/* @jsxRuntime classic */\n/* @jsx mdx */\n\nvar _frontmatter = {\n  \"localeCode\": \"en-US\",\n  \"order\": 3,\n  \"category\": \"Ecosystem\",\n  \"title\": \"React 19 Adaptation\",\n  \"icon\": \"doc-configprovider\",\n  \"dir\": \"column\",\n  \"brief\": \"React 19 adaptation guide\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Semi Design now supports React 19. Due to some underlying API changes in React 19, a simple adaptation is required.\"), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"What's Special About React 19\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"React 19 removed two APIs that Semi components depend on:\"), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"1. \", mdx(\"inlineCode\", {\n    parentName: \"h3\"\n  }, \"ReactDOM.render\"), \" Removed\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"React 19 removed the legacy \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ReactDOM.render\"), \" API in favor of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createRoot\"), \". The following Semi components rely on this API to dynamically mount content:\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Modal.info()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Modal.success()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Modal.error()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Modal.warning()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Modal.confirm()\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Toast.info()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Toast.success()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Toast.error()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Toast.warning()\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Notification.info()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Notification.success()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Notification.error()\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Notification.warning()\"))), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"2. \", mdx(\"inlineCode\", {\n    parentName: \"h3\"\n  }, \"ReactDOM.findDOMNode\"), \" Removed\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"React 19 removed the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ReactDOM.findDOMNode\"), \" API, which was used to get the DOM node from a class component instance. The following Semi components are affected:\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Tooltip\"), \" and all popup components based on it (\", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Popover\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"PopConfirm\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Dropdown\"), \", etc.)\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Why Do We Need an Adapter\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Since Semi needs to support React 16/17/18/19 simultaneously, and React 19's \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createRoot\"), \" is located in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"react-dom/client\"), \" subpath, directly importing it in the library would cause errors in older React versions. Therefore, we use an adapter pattern that allows React 19 users to explicitly inject the required API.\")), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Quick Start\"), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Installation\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Use the same package regardless of whether you're using React 16, 17, 18, or 19:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"# npm\\nnpm install @douyinfe/semi-ui\\n\\n# yarn\\nyarn add @douyinfe/semi-ui\\n\\n# pnpm\\npnpm add @douyinfe/semi-ui\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"React 19 Users (Important)\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"If your project uses \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"React 19\"), \", you need to import the adapter at the \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"very top\"), \" of your entry file:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"// main.tsx or index.tsx\\n// \\u26A0\\uFE0F Must be imported at the top, before any Semi components\\nimport '@douyinfe/semi-ui/react19-adapter';\\n\\nimport ReactDOM from 'react-dom/client';\\nimport App from './App';\\n\\nReactDOM.createRoot(document.getElementById('root')!).render(<App />);\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Then use Semi components as usual:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"// App.tsx\\nimport { Button, Toast, Modal, Notification } from '@douyinfe/semi-ui';\\n\\nfunction App() {\\n    const showToast = () => {\\n        Toast.success('Operation successful!');\\n    };\\n\\n    const showModal = () => {\\n        Modal.confirm({\\n            title: 'Confirm',\\n            content: 'Are you sure you want to proceed?',\\n        });\\n    };\\n\\n    return (\\n        <div>\\n            <Button onClick={showToast}>Show Toast</Button>\\n            <Button onClick={showModal}>Show Modal</Button>\\n        </div>\\n    );\\n}\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"React 16/17/18 Users\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"For React 16, 17, or 18 projects, \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"no additional configuration is needed\"), \":\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"import { Button, Toast } from '@douyinfe/semi-ui';\\n\\nfunction App() {\\n    return (\\n        <Button onClick={() => Toast.success('Hello Semi!')}>\\n            Click me\\n        </Button>\\n    );\\n}\\n\"))), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Notes\"), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Tooltip and Class Component Limitations\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Due to the removal of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ReactDOM.findDOMNode\"), \" in React 19, when the children of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Tooltip\"), \" (and components based on it like \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Popover\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"PopConfirm\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dropdown\"), \", etc.) is a \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"class component\"), \", it may not be able to correctly get the DOM node for positioning.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Affected scenarios\"), \":\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"// \\u274C Class component as direct child of Tooltip may not position correctly\\nclass MyComponent extends React.Component {\\n    render() {\\n        return <span {...this.props}>Content</span>;\\n    }\\n}\\n\\n<Tooltip content=\\\"Tip\\\">\\n    <MyComponent />\\n</Tooltip>\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Solution\"), \": Wrap the class component with a DOM element\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"// \\u2705 Recommended: wrap with a DOM element\\n<Tooltip content=\\\"Tip\\\">\\n    <span>\\n        <MyComponent />\\n    </span>\\n</Tooltip>\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Unaffected scenarios\"), \":\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Function components that correctly forward ref using \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"forwardRef\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Native DOM elements (like \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"<span>\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"<div>\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"<button>\"), \", etc.)\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Error Messages\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"If you forget to import the adapter in React 19, the console will display:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"[Semi UI] createRoot is not available. \\nIf you are using React 19, please inject createRoot before using Semi components.\\nFor details, see: https://semi.design/zh-CN/ecosystem/react19\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"When you see this error, add the following at the top of your entry file:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import '@douyinfe/semi-ui/react19-adapter';\\n\"))), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"FAQ\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Q: Will importing the adapter in React 18 cause issues?\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"A: No. In React 18, Semi automatically detects and uses the built-in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createRoot\"), \". Importing the adapter has no side effects.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Q: What does the adapter do?\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"A: The adapter does one thing: inject React 19's \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createRoot\"), \" function into Semi's internals, enabling Modal, Toast, Notification, and similar components to work properly. The code is very simple:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import { createRoot } from 'react-dom/client';\\nimport semiGlobal from './_utils/semi-global';\\n\\nsemiGlobal.config.createRoot = createRoot;\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Q: Why must the adapter be imported at the very top?\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"A: Because the adapter needs to inject \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createRoot\"), \" before any Semi components are rendered. If imported after components have started rendering, the first render may fail.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Q: I was using \", mdx(\"inlineCode\", {\n    parentName: \"strong\"\n  }, \"@douyinfe/semi-ui-19\"), \", how do I migrate?\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"A: \"), mdx(\"ol\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Uninstall \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"@douyinfe/semi-ui-19\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Install \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"@douyinfe/semi-ui\"), \" (if not already installed)\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Change all \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"from '@douyinfe/semi-ui-19'\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"from '@douyinfe/semi-ui'\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Add \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"import '@douyinfe/semi-ui/react19-adapter'\"), \" at the top of your entry file\"))), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Technical Details\"), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Version Compatibility Matrix\"), mdx(\"table\", {\n    parentName: \"section\"\n  }, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"React Version\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Adapter Required\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"th\"\n  }, \"ReactDOM.render\")), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"th\"\n  }, \"createRoot\")))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"16.x\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"No\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u2705 Used\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u274C Not available\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"17.x\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"No\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u2705 Used\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u274C Not available\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"18.x\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"No\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u26A0\\uFE0F Deprecated\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u2705 Auto-detected\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"19.x\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Yes\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u274C Removed\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u2705 Needs injection\")))), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"How the Adapter Works\"), mdx(\"ol\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"React 16/17: Uses legacy \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ReactDOM.render\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ReactDOM.unmountComponentAtNode\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"React 18: Automatically detects and uses \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"createRoot\"), \" exported from \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"react-dom\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"React 19: \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"createRoot\"), \" is no longer exported directly from \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"react-dom\"), \", needs to be imported from \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"react-dom/client\"), \" and injected via adapter\"))));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"slug":"en-US/ecosystem/react19","next":{"fields":{"slug":"zh-CN/ecosystem/react19"},"id":"23213262-3b95-5e10-9ded-f3ff58c528d6","frontmatter":{"title":"React 19 适配","localeCode":"zh-CN","icon":"doc-configprovider","showNew":null}},"previous":{"fields":{"slug":"zh-CN/start/getting-started"},"id":"f6ab8d8f-d12b-55d3-a19e-5fba1f618927","frontmatter":{"title":"Getting Started 快速开始","localeCode":"zh-CN","icon":"doc-gettingstarted","showNew":null}}}},"staticQueryHashes":["1348983216229725","1477422646229725","3245198693229725","417590761229725","63159454229725"]}