Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Server-Side Search With searchCriteria Filters

Server-Side Search With searchCriteria Filters

~13 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

EXACTLY the same server-side search logic as the React web tutorial – here combined with a TextInput and FlatList's ListHeaderComponent prop, so the search bar scrolls WITH the list.

api/magentoApi.js
// ... previous code ...

export async function fetchProducts({
  page = 1,
  sortField = 'name',
  direction = 'ASC',
  query = '',
} = {}) {
  const params = new URLSearchParams({
    'searchCriteria[pageSize]': PAGE_SIZE,
    'searchCriteria[currentPage]': page,
    'searchCriteria[sortOrders][0][field]': sortField,
    'searchCriteria[sortOrders][0][direction]': direction,
  });

  if (query.trim() !== '') {
    params.set('searchCriteria[filterGroups][0][filters][0][field]', 'name');
    params.set('searchCriteria[filterGroups][0][filters][0][value]', `%${query}%`);
    params.set('searchCriteria[filterGroups][0][filters][0][condition_type]', 'like');
  }

  const data = await magentoFetch(`/products?${params.toString()}`);
  return {
    products: data.items,
    totalCount: data.total_count,
    pageCount: Math.ceil(data.total_count / PAGE_SIZE),
  };
}

components/SearchBar.js

components/SearchBar.js
import { useState } from 'react';
import { TextInput, Button, View, StyleSheet } from 'react-native';

export default function SearchBar({ onSearch }) {
  const [input, setInput] = useState('');

  return (
    <View style={styles.row}>
      <TextInput
        style={styles.input}
        placeholder="Search products..."
        value={input}
        onChangeText={setInput}
        onSubmitEditing={() => onSearch(input)}
        returnKeyType="search"
      />
      <Button title="Search" onPress={() => onSearch(input)} />
    </View>
  );
}

const styles = StyleSheet.create({
  row: { flexDirection: 'row', alignItems: 'center', padding: 16, gap: 8 },
  input: { flex: 1, borderWidth: 1, borderColor: '#ccc', borderRadius: 6, padding: 8 },
});

onSubmitEditing additionally triggers the search when the "search" key is pressed on the on-screen keyboard – a mobile interaction pattern solved differently in the React web tutorial (via <form onSubmit>).

screens/ProductListScreen.js
import { useEffect, useState } from 'react';
import { FlatList, ActivityIndicator, StyleSheet } from 'react-native';
import { fetchProducts } from '../api/magentoApi';
import ProductCard from '../components/ProductCard';
import SearchBar from '../components/SearchBar';

export default function ProductListScreen() {
  const [products, setProducts] = useState([]);
  const [page, setPage] = useState(1);
  const [pageCount, setPageCount] = useState(1);
  const [query, setQuery] = useState('');
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);

  useEffect(() => {
    setLoading(true);
    async function searchAndLoad() {
      const result = await fetchProducts({ page: 1, query });
      setProducts(result.products);
      setPageCount(result.pageCount);
      setPage(1);
      setLoading(false);
    }
    searchAndLoad();
  }, [query]);

  async function loadNextPage() {
    if (loadingMore || page >= pageCount) {
      return;
    }
    setLoadingMore(true);
    const nextPage = page + 1;
    const result = await fetchProducts({ page: nextPage, query });
    setProducts((previous) => [...previous, ...result.products]);
    setPage(nextPage);
    setLoadingMore(false);
  }

  return (
    <FlatList
      data={products}
      keyExtractor={(product) => product.sku}
      renderItem={({ item }) => <ProductCard product={item} />}
      ListHeaderComponent={<SearchBar onSearch={setQuery} />}
      ListEmptyComponent={
        loading ? <ActivityIndicator size="large" /> : null
      }
      onEndReached={loadNextPage}
      onEndReachedThreshold={0.5}
      ListFooterComponent={loadingMore ? <ActivityIndicator /> : null}
    />
  );
}

const styles = StyleSheet.create({});

ListHeaderComponent renders SearchBar as PART of the list – it scrolls along, instead of being pinned to the top of the screen. [query] as the useEffect dependency automatically reloads from page 1 whenever the search term changes – setPage(1) prevents the same subtle bug as in the React web tutorial.

Tipp: Search for a word fragment you'd expect in SEVERAL of your real product names – if only matching results show up, AND loading more works correctly within the filtered results, server-side search is working as intended.