This issue is to notify plugin maintainers about required compatibility testing and updates for the React 18 upgrade in OpenSearch Dashboards.
Related PRs/Issues:
Timeline
- Testing deadline: February 6, 2026
Changes Implemented
OpenSearch Dashboards has upgraded from React 16.14.0 to React 18.2.0. Key package changes include:
| Package |
Old Version |
New Version |
| react |
16.14.0 |
18.2.0 |
| react-dom |
16.12.0 |
18.2.0 |
| @types/react |
16.14.23 |
18.2.0 |
| @testing-library/react |
12.1.5 |
14.0.0 |
| react-redux |
7.2.0 |
8.1.0 |
Note: @testing-library/react-hooks has been removed and merged into @testing-library/react.
Breaking Changes Requiring Plugin Updates
1. ReactDOM.render Migration (Required - breaks compilation)
Replace deprecated ReactDOM.render() with createRoot():
// Old approach (React 16/17)
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, params.element);
return () => ReactDOM.unmountComponentAtNode(params.element);
// New approach (React 18)
import { createRoot } from 'react-dom/client';
const root = createRoot(params.element);
root.render(<App />);
return () => root.unmount();
Find instances in your plugin:
grep -r "ReactDOM.render\|unmountComponentAtNode" --include="*.js" --include="*.tsx" --include="*.ts"
2. React.FC Children Prop (Required for TypeScript)
React 18 no longer implicitly includes children in React.FC props:
// Old (React 16/17)
const MyComponent: React.FC<Props> = ({ children }) => { ... }
// New (React 18) - explicitly declare children
interface Props {
data: string;
children?: React.ReactNode;
}
const MyComponent: React.FC<Props> = ({ data, children }) => { ... }
3. Testing Library Updates (Required)
// Old imports
import { renderHook, act } from '@testing-library/react-hooks';
import Adapter from 'enzyme-adapter-react-16';
// New imports
import { renderHook, act } from '@testing-library/react';
import Adapter from '@cfaester/enzyme-adapter-react-18';
4. Unsafe Lifecycle Methods (Required - throws errors)
Replace deprecated lifecycle methods:
componentWillMount → componentDidMount
componentWillReceiveProps → componentDidUpdate
componentWillUpdate → componentDidUpdate
Verification Steps
-
Setup Environment:
git clone https://github.com/opensearch-project/OpenSearch-Dashboards
cd OpenSearch-Dashboards
git checkout main
yarn osd bootstrap
-
Install Your Plugin:
cd plugins
git clone <your-plugin-repo>
cd <plugin-directory>
yarn osd bootstrap
cd ../../
yarn start
-
Validation Tasks:
Important Notes for React 18
- Async Rendering:
createRoot().render() is asynchronous. If your plugin measures DOM immediately after rendering (e.g., D3 visualizations), you may need flushSync to force synchronous updates.
- External State: If subscribing to external state managers, consider using
useSyncExternalStore instead of useEffect + useState pattern.
Required Actions
Contacts
OpenSearch Dashboards Team
This issue is to notify plugin maintainers about required compatibility testing and updates for the React 18 upgrade in OpenSearch Dashboards.
Related PRs/Issues:
Timeline
Changes Implemented
OpenSearch Dashboards has upgraded from React 16.14.0 to React 18.2.0. Key package changes include:
Note:
@testing-library/react-hookshas been removed and merged into@testing-library/react.Breaking Changes Requiring Plugin Updates
1. ReactDOM.render Migration (Required - breaks compilation)
Replace deprecated
ReactDOM.render()withcreateRoot():Find instances in your plugin:
2. React.FC Children Prop (Required for TypeScript)
React 18 no longer implicitly includes
childreninReact.FCprops:3. Testing Library Updates (Required)
4. Unsafe Lifecycle Methods (Required - throws errors)
Replace deprecated lifecycle methods:
componentWillMount→componentDidMountcomponentWillReceiveProps→componentDidUpdatecomponentWillUpdate→componentDidUpdateVerification Steps
Setup Environment:
git clone https://github.com/opensearch-project/OpenSearch-Dashboards cd OpenSearch-Dashboards git checkout main yarn osd bootstrapInstall Your Plugin:
Validation Tasks:
Important Notes for React 18
createRoot().render()is asynchronous. If your plugin measures DOM immediately after rendering (e.g., D3 visualizations), you may needflushSyncto force synchronous updates.useSyncExternalStoreinstead ofuseEffect + useStatepattern.Required Actions
Contacts
OpenSearch Dashboards Team