๐ฅ Debounce
๋ฌธ์
input์ ๊ฐ์ด ์
๋ ฅ๋ ๋๋ง๋ค ๊ฒ์๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์ ํ๋ค. ํ์ง๋ง onChange๊ฐ ์ด๋ฃจ์ด์ง ๋๋ง๋ค ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ด๋ฉด 2๊ฐ์ง ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
๋ ๊ฐ์ง ๋ฌธ์ ์ ์ ํด๊ฒฐํ๊ธฐ ์ํด Debouce๋ฅผ ๊ตฌํํ๊ณ ์ ํ๋ค.
lodash๋ฅผ ์ฌ์ฉํ์ฌ Debouce ๊ตฌํํ๊ธฐ
import React, { useCallback, useMemo, useState } from "react";
import { debounce } from "lodash";
import { ICharacter } from "./types";
async function searchCharacter(keyword: string): Promise<ICharacter[]> {
const response = await fetch(
`https://swapi.dev/api/people?search=${keyword}`
).then((res) => res.json());
return response.results;
}
function App() {
const [keyword, setKeyword] = useState("");
const [data, setData] = useState<ICharacter[]>([]);
// ์ฒซ๋ฒ์งธ ์ธ์๋ก๋ ์ฝ๋ฐฑํจ์, ๋ ๋ฒ์งธ ์ธ์๋ก๋ ์๊ฐ(๋ฐ๋ฆฌ์ธ์ปจ๋)๋ฅผ ์ ๋ฌํด์ค๋ค.
// searchCharacter๊ฐ 1์ด ๋์ ์คํ๋์ง ์๋๋ค๋ฉด ๊ทธ ๋ ์์ฒญ์ ๋ณด๋ธ๋ค.
const handleSearch = useCallback(
debounce((keyword: string) => {
searchCharacter(keyword).then((res) => setData(res));
}, 1000),
[]
);
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
setKeyword(e.target.value);
handleSearch(e.target.value);
},
[handleSearch]
);
return (
<div className="App">
<form>
<input type="text" onChange={handleChange} value={keyword} />
</form>
<ul>
{data?.map((item, i) => (
<li key={i}>{item.name}</li>
))}
</ul>
</div>
);
}
export default App;
useCallback์ ESLint ๊ฒฝ๊ณ ๋ฐ์
React Hook useCallback received a function whose dependencies are unknown.
Pass an inline function instead.eslintreact-hooks/exhaustive-deps
โ ย ํด๊ฒฐ๋ฐฉ๋ฒ
useCallback โ useMemo๋ก ๋ณ๊ฒฝ
const handleSearch = useMemo(
() =>
debounce((keyword: string) => {
searchCharacter(keyword).then((res) => setData(res));
}, 1000),
[]
);