From 21245a193202d0d64dabe42b49f0132974c5432e Mon Sep 17 00:00:00 2001 From: Mathea Liv Date: Tue, 13 Oct 2026 17:24:54 +0200 Subject: [PATCH] =?UTF-8?q?[feat]=20legg=20til=20s=C3=B8k=20med=20debounce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 17 ++++++++++++----- src/components/SearchBar.tsx | 15 +++++++++++++-- src/graphql/countries.ts | 4 ++-- src/hooks/useDebounce.ts | 12 ++++++++++++ 4 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 src/hooks/useDebounce.ts diff --git a/src/App.tsx b/src/App.tsx index 97a015e..63373e7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,28 +6,35 @@ import { SearchBar } from './components/SearchBar'; import { CountryDetailPage } from './pages/CountryDetailPage'; import type { Country } from './types/country'; import { GET_COUNTRIES } from './graphql/countries'; +import { useDebounce } from './hooks/useDebounce'; function App() { const [selectedCode, setSelectedCode] = useState(null); + const [searchText, setSearchText] = useState(''); + const search = useDebounce(searchText.trim(), 300); + const { loading, error, data } = useQuery<{ countries: { items: Country[]; totalCount: number }; }>(GET_COUNTRIES, { - variables: { limit: 20, offset: 0 }, + variables: { search: search || null, limit: 20, offset: 0 }, }); - if (loading) return

Loading countries...

; - if (error) return

Error loading countries: {error.message}

; - const countries = data?.countries.items ?? []; const selectedCountry = countries.find((country) => country.code === selectedCode) ?? null; return ( <>

Countries

- {!selectedCode && } + {!selectedCode && } {selectedCode && selectedCountry ? ( setSelectedCode(null)} /> + ) : error ? ( +

Error loading countries: {error.message}

+ ) : loading ? ( +

Loading countries...

+ ) : countries.length === 0 ? ( +

No countries found.

) : ( setSelectedCode(country.code)} /> )} diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index b6d4f9f..5fb3e7c 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -1,8 +1,19 @@ -export function SearchBar() { +interface SearchBarProps { + value: string; + onChange: (value: string) => void; +} + +export function SearchBar({ value, onChange }: SearchBarProps) { return ( - + onChange(event.target.value)} + /> ); } diff --git a/src/graphql/countries.ts b/src/graphql/countries.ts index 39c0603..e536dc3 100644 --- a/src/graphql/countries.ts +++ b/src/graphql/countries.ts @@ -1,8 +1,8 @@ import { gql } from '@apollo/client'; export const GET_COUNTRIES = gql` - query GetCountries($limit: Int!, $offset: Int!) { - countries(limit: $limit, offset: $offset) { + query GetCountries($search: String, $limit: Int!, $offset: Int!) { + countries(search: $search, limit: $limit, offset: $offset) { items { code name diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts new file mode 100644 index 0000000..e5a306e --- /dev/null +++ b/src/hooks/useDebounce.ts @@ -0,0 +1,12 @@ +import { useEffect, useState } from 'react'; + +export function useDebounce(value: T, delayMs: number): T { + const [debounced, setDebounced] = useState(value); + + useEffect(() => { + const timer = setTimeout(() => setDebounced(value), delayMs); + return () => clearTimeout(timer); + }, [value, delayMs]); + + return debounced; +}