# Part 83: Enhancing the Search Experience: From Test Data to Real-time Search in Next.Js

<figure><img src="https://159896965-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3LclXKUpANLoSt8DPdYV%2Fuploads%2FJK8G3Yjm1qHwjGSqwUcV%2F1675674296261.jpeg?alt=media&#x26;token=989182c4-9098-4bba-8dd9-52aeb4b0f941" alt=""><figcaption><p>[App] Client-Side Data Fetching</p></figcaption></figure>

The power of a search feature lies in its ability to quickly and accurately deliver relevant results to users. Our SearchBox component was initially built using test data, which limited its functionality. Now, it's time to elevate the user experience by enabling the search across all available reviews, ensuring users can find exactly what they're looking for. In this post, we'll explore how to achieve this by fetching real data and optimizing our component for a seamless search experience.

### Transitioning from Test Data to Real Data

#### Understanding Client vs. Server Components

Our SearchBox is a Client Component, which means it cannot directly fetch data in the same way a Server Component can. Server Components can declare their functions as asynchronous and perform data fetching within them, but this isn't possible for Client Components. However, we can use a clever workaround: fetching data in a Server Component and passing it as a prop to the Client Component.

#### Fetching Data in the Server Component

We begin by updating our `ReviewsPage` component, which is a Server Component. Here, we can load the data we need and pass it down to the SearchBox.

1. **Define a New Data Fetching Function**: We create a new function `getSearchableReviews` that fetches the `slug` and `title` for all reviews:

   ```javascript
   //lib/reviews.js
   export async function getSearchableReviews() {
     const { data } = await fetchReviews({
       fields: ['slug', 'title'],
       sort: ['publishedAt:desc'],
       pagination: { pageSize: 100 },
     });
     return data.map(({ attributes }) => ({
       slug: attributes.slug,
       title: attributes.title,
     }));
   }
   ```
2. **Integrate Data Fetching in `ReviewsPage`**: We call this new function within the `ReviewsPage` component and pass the result to the `SearchBox`.

   <pre class="language-javascript"><code class="lang-javascript">import { getReviews, getSearchableReviews } from '@/lib/reviews';

   export default async function ReviewsPage({ searchParams }) {
     const page = parsePageParam(searchParams.page);
     const { reviews, pageCount } = await getReviews(PAGE_SIZE, page);
     <a data-footnote-ref href="#user-content-fn-1">const searchableReviews = await getSearchableReviews();</a>
     console.log('[ReviewsPage] rendering:', page);
     return (
       &#x3C;>
         &#x3C;Heading>Reviews&#x3C;/Heading>
         &#x3C;div className="flex justify-between pb-3">
           &#x3C;PaginationBar href="/reviews" page={page} pageCount={pageCount} />
           <a data-footnote-ref href="#user-content-fn-1">&#x3C;SearchBox reviews={searchableReviews} /></a>
         &#x3C;/div>
         &#x3C;ul className="flex flex-row flex-wrap gap-3">
           {reviews.map((review, index) => (

   </code></pre>

### Optimizing the Search Functionality

With real data now available to the SearchBox, we need to enhance its functionality to ensure a smooth user experience.

#### Implementing Case-Insensitive Search

To make the search case-insensitive, we convert both the review titles and the user's query to lowercase before performing the search.

```javascript
//SearchBox.jsx

//remove const reviews = [


export default function SearchBox(reviews) {

  const filtered = reviews.filter((review) =>
    review.title.toLowerCase().includes(query.toLowerCase())
  ).slice(0, 5);

```

#### Limiting Search Results

To prevent overwhelming the user with too many results, we limit the number of displayed options to five. This is achieved using the `slice` method.

### Understanding Data Flow

The SearchBox component receives the `reviews` prop from the `ReviewsPage`, which is a Server Component. This data is passed through JavaScript injected into the page by Next.js, ensuring it can be used by the Client Component to filter results dynamically.

#### Considerations for Data Passing

While this method effectively provides the SearchBox with the necessary data, it's important to be mindful of the potential increase in page size. The data is passed as a JavaScript object, increasing the page's weight. In scenarios where the data set might grow significantly, alternative strategies, such as client-side fetching, could be explored to maintain optimal performance.

### Conclusion

By fetching real data and enhancing the search logic, we've transformed our SearchBox into a robust and efficient tool for navigating reviews. This approach demonstrates the power of integrating client-side interactivity with server-side data handling, a crucial technique for modern web applications. As we continue to refine this feature, exploring client-side data fetching will open new doors for further improvements in scalability and performance. Stay tuned for more updates as we continue to enhance our application's search capabilities!

[^1]:
