
์ฑ์ ๋ง๋ค๋ค ๋ณด๋ฉด ์ ์ ๋ฆฌ์คํธ, ์ํ ๋ชฉ๋ก, ๊ฒ์๊ธ ๋ฑ์์ ๊ฒ์ ๊ธฐ๋ฅ์ด ๊ผญ ํ์ํด์ง๋ค.
์ฒ์์๋ ๋จ์ํ TextInput ํ๋ ๋ฃ๊ณ includes()๋ก ํํฐ๋ง๋ง ํ๋ฉด ๋ ์ค ์์๋๋ฐ,
๋ง์ ์ฌ์ฉ์ ์
์ฅ์์ ์๊ฐํด๋ณด๋ ๊ฒ์์ ์๊ฐ๋ณด๋ค ์ ๊ฒฝ ์จ์ผ ํ ํฌ์ธํธ๊ฐ ๋ง์๋ค.
์ด๋ฒ ๊ธ์์๋ ๋ด๊ฐ ์ค์ ๋ก ๊ฒ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ฉด์ ๊ฒช์๋
๊ฒ์ ์ธํ ์ฒ๋ฆฌ, ๋๋ฐ์ด์ฑ, ํํฐ๋ง, ์น์
๋ฆฌ์คํธ, ์ต๊ทผ ๊ฒ์์ด ์ ์ฅ๊น์ง์ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณธ๋ค.
| ํญ๋ชฉ | ์ค๋ช |
|---|---|
| UX ํฅ์ | ์ํ๋ ์ ๋ณด๋ฅผ ๋น ๋ฅด๊ฒ ์ฐพ์ ์ ์์ด์ผ ์ฑ ๋ง์กฑ๋๊ฐ ์ฌ๋ผ๊ฐ๋ค |
| ๋ฐ์ดํฐ ๋ง์์๋ก ํ์ | ์์ญ ๊ฐ ์ด์์ ๋ฆฌ์คํธ์์๋ ๊ฒ์ ์์ด๋ ํ์์ด ์ด๋ ต๋ค |
| ์ค์๊ฐ ๋ฐ์ | ๊ฒ์์ด์ ๋ฐ๋ผ ์ค์๊ฐ์ผ๋ก ๊ฒฐ๊ณผ๊ฐ ๋ฐ๋๋ ๊ฒฝํ์ด ์ค์ํ๋ค |
const [query, setQuery] = useState('');
const [filteredData, setFilteredData] = useState(data);
useEffect(() => {
const newData = data.filter(item => item.name.includes(query));
setFilteredData(newData);
}, [query]);
<TextInput
value={query}
onChangeText={setQuery}
placeholder="๊ฒ์์ด๋ฅผ ์
๋ ฅํ์ธ์"
/>
์
๋ ฅ์ด ๋ฐ๋ ๋๋ง๋ค ํํฐ๋งํ๋ฉด ๋๋ฌด ์์ฃผ ์ฐ์ฐ์ด ๋ฐ์ํ๋ค.
๊ทธ๋์ ๋๋ฐ์ด์ฑ์ ํตํด ์
๋ ฅ์ด ์ ์ ๋ฉ์ท์ ๋๋ง ํํฐ๋งํ๋๋ก ๋ง๋ค์๋ค.
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debouncedValue;
}
const debouncedQuery = useDebounce(query, 300);
useEffect(() => {
const newData = data.filter(item => item.name.includes(debouncedQuery));
setFilteredData(newData);
}, [debouncedQuery]);
๋ฐ์ดํฐ๊ฐ ๋ง์ ๊ฒฝ์ฐ, ์๋ฅผ ๋ค์ด ์ ์ ์ด๋ฆ์ด ๊ฐ๋๋ค์์ผ๋ก ๋์ด ์๊ฑฐ๋
๋ ์ง ๊ธฐ์ค์ผ๋ก ๋๋๋ค๋ฉด SectionList๊ฐ ๊ฝค ์ ์ฉํ๋ค.
<SectionList
sections={filteredSections}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Text>{item.name}</Text>}
renderSectionHeader={({ section }) => <Text>{section.title}</Text>}
/>
const filteredSections = [
{
title: 'A',
data: [{ id: '1', name: 'Alex' }, { id: '2', name: 'Amber' }],
},
{
title: 'B',
data: [{ id: '3', name: 'Ben' }],
},
];
์ฌ์ฉ์๊ฐ ๊ฒ์ํ๋ ๋ด์ฉ์ ์ ์ฅํด๋๋ฉด ํธ์์ฑ์ด ์ฌ๋ผ๊ฐ๋ค.
React Native์์ AsyncStorage๋ฅผ ํ์ฉํ ์ ์๋ค.
import AsyncStorage from '@react-native-async-storage/async-storage';
const saveSearch = async (keyword: string) => {
const prev = await AsyncStorage.getItem('recent_keywords');
const parsed = prev ? JSON.parse(prev) : [];
const updated = [keyword, ...parsed.filter(k => k !== keyword)].slice(0, 10);
await AsyncStorage.setItem('recent_keywords', JSON.stringify(updated));
};
๊ฒ์ ์คํ ์ saveSearch(query)๋ง ํธ์ถํ๋ฉด ๋๋ค.
์ฒ์์๋ ๋จ์ํ๊ฒ ๋ฌธ์์ด ํฌํจ ์ฌ๋ถ๋ง ์ฒดํฌํ๋๋ฐ,
๊ทธ๋์ ๋๋ฐ์ด์ฑ, ์น์
๋ฆฌ์คํธ, ์ ์ฅ๊น์ง ํ๋์ฉ ๊ฐ์ ํ๋ค.
ํนํ useDebounce๋ ์ด๋๋ ์ธ ์ ์์ด์ ์ง๊ธ์ ๊ณตํต ํ
์ผ๋ก ๋นผ์ ์ฐ๊ณ ์๋ค.
๐ ๊ฒ์์ ๋จ์ํ ๊ธฐ๋ฅ ๊ฐ์ง๋ง, ์์ ๋ํ ์ผ์ด ์ ์ฒด UX๋ฅผ ๋ฐ๊พผ๋ค.