Next.js (React) Component Filter table results without re-rendering input

I have a Next.js client component which shows a data table and has a search bar which can be used to filter the table. The issue is that whenever I type in the search bar, it causes the whole component to re-render, which means the search loses focus and interrupts typing. I have the search debounced but it still has an effect for longer queries.

'use client'

import { useEffect, useState } from "react";
import { PartsTable as PartsRow } from "@/app/lib/definitions";
import PartsTable from "@/app/ui/parts/table";
import NoQueryParamSearch from "../no-query-param-search";

export default function PartSearch({
    onPartSelected
}: {
    onPartSelected?: any
}) {
    const [parts, setParts] = useState([] as PartsRow[]);
    const [search, setSearch] = useState('');
    useEffect(() => {
        fetch(`/api/parts?query=${search}`).then(async (response) => {
            const parts = await response.json();
            setParts(parts);
        });
    }, [search]);
    const handlePartRowClicked = (part: any) => {
        onPartSelected(part);
    }
    const handleQueryChanged = (query: string) => {
        setSearch(query);
    }
    return (
        <div>
            <NoQueryParamSearch placeholder="Search ID, description, year, etc..." onChange={handleQueryChanged} />
            <div className="border border-solid border-gray-200 rounded-md my-2">
                <PartsTable parts={parts.slice(0, 5)} onRowClick={handlePartRowClicked} disableControls />
            </div>
        </div>
    );
}
'use client';

import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { useDebouncedCallback } from 'use-debounce';

export default function NoQueryParamSearch({ placeholder, onChange, autoComplete = true }: { placeholder: string, onChange: any, autoComplete?: boolean }) {

    const handleSearch = useDebouncedCallback((term) => {
        onChange(term);
    }, 300);

    return (
        <div className="relative flex flex-shrink-0">
            <label htmlFor="search" className="sr-only">
                Search
            </label>
            <input
                className="peer block w-96 rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
                placeholder={placeholder}
                onChange={(e) => {
                    handleSearch(e.target.value);
                }}
                autoComplete={autoComplete ? undefined : 'off'}
                autoCorrect={autoComplete ? undefined : 'off'}
            />
            <MagnifyingGlassIcon className="absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" />
        </div>
    );
}

This needs to be a client component because of onPartSelected. When a row is selected it needs to send that to the parent component.