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.tsx
  • src/components/search/Facet.tsx
  • src/components/search/Facets.tsx
  • src/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

PackageReact 18React 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

  1. Upgrade @elastic/react-search-ui to 1.24.2 or later
  2. Handle the WithSearch type definition changes (undefined handling)
  3. Next.js 15.5.9 is recommended (16 has many breaking changes)

Created: 2026-01-19