Introduction
When trying to use @elastic/react-search-ui in a project using React 19 and Next.js 15, you may encounter the following dependency error:
npm error ERESOLVE could not resolve
npm error peer react@">= 16.8.0 < 19" from @elastic/react-search-ui@1.23.1
This article explains the cause of this problem and the solution in detail.
Cause of the Problem
The peer dependency of @elastic/react-search-ui@1.23.1 was set to react@">= 16.8.0 < 19", which did not support React 19.
Solution
1. Package Upgrade
In May 2025, PR #1162 was merged, adding React 19 support. Use version 1.24.2 or later.
// package.json
{
"dependencies": {
- "@elastic/react-search-ui": "^1.23.1",
- "@elastic/react-search-ui-views": "^1.23.1",
- "@elastic/search-ui": "^1.23.1",
+ "@elastic/react-search-ui": "^1.24.2",
+ "@elastic/react-search-ui-views": "^1.24.2",
+ "@elastic/search-ui": "^1.24.2",
- "next": "15.3.8",
+ "next": "15.5.9",
}
}
2. Handling Type Definition Changes
In 1.24.2, the type definition of the WithSearch component has changed. The filters in SearchContextState is now Filter[] | undefined.
Before (1.23.x)
type SearchContext = {
filters: Filter[];
setFilter: (field: string, value: FilterValue) => void;
removeFilter: (field: string) => void;
};
<WithSearch
mapContextToProps={({ filters, setFilter, removeFilter }: SearchContext) => ({
filters,
setFilter,
removeFilter,
})}
>
{({ filters, setFilter, removeFilter }: SearchContext) => (
<MyComponent filters={filters} />
)}
</WithSearch>
After (1.24.x)
// Remove custom type definitions and rely on type inference
<WithSearch
mapContextToProps={({ filters, setFilter, removeFilter }) => ({
filters,
setFilter,
removeFilter,
})}
>
{({ filters, setFilter, removeFilter }) => (
<MyComponent
filters={filters ?? []} // Handle undefined
setFilter={setFilter!} // Non-null assertion
removeFilter={removeFilter!}
/>
)}
</WithSearch>
3. setFilter Type Change
The type of setFilter has also changed.
// Before: Custom definition
setFilter: (field: string, value: FieldValue[], operator: 'all' | 'any', negate: boolean) => void
// After: Use the actual type from search-ui
import type { FilterValue, FilterType } from '@elastic/search-ui';
setFilter: (name: string, value: FilterValue, type?: FilterType, persistent?: boolean) => void
The call site also needs to be updated:
// Before
setFilter(field, values, 'all', false);
// After (add type assertion)
setFilter(field, values as FilterValue, 'all', false);
Example Files That Need Changes
In this project, the following files were modified:
src/components/page/search/Range.tsxsrc/components/search/Facet.tsxsrc/components/search/Facets.tsxsrc/components/search/Filters.tsx
Note: Migration to Next.js 16
I also attempted migration to Next.js 16, but there were many breaking changes that required additional work:
- Dependency on React 19.2
- Renaming of middleware to proxy
- Turbopack as the default
- Enforcement of async APIs
If stability is a priority, running on Next.js 15.5.9 is recommended.
Version Compatibility Table
| Package | React 18 | React 19 |
|---|---|---|
| @elastic/react-search-ui 1.23.x | ✅ | ❌ |
| @elastic/react-search-ui 1.24.2+ | ✅ | ✅ |
| Next.js 15.5.x | ✅ | ✅ |
| Next.js 16.x | - | ✅ (requires additional work) |
Summary
- Upgrade
@elastic/react-search-uito 1.24.2 or later - Handle the
WithSearchtype definition changes (undefined handling) - Next.js 15.5.9 is recommended (16 has many breaking changes)
Reference Links
Created: 2026-01-19