Autocomplete
해당 포스트는 제로베이스 오프라인스쿨 진행 과정 중 React PairProgramming과제를 진행하며 회고를 정리하는 글이다.
1. image 파일 경로
- 현상
images 폴더를 src 경로에 저장했더니 404 Error가 발생하였다.
- 발견
images폴더를 public경로로 이동하였더니 해결되었다.
- 배운점
src폴더에 images 폴더 경로를 지정하면 이미지 파일을 사용할 때마다 매번 import를 해야 하는 번거로움이 있지만, public폴더에 images 폴더 경로를 지정하면 매번 import 하지 않아도 된다는 것을 알게 되었다.
- 선언
에셋을 가져올 때 어디에 지정을 할지 잘 생각하는 습관을 가져야겠다.
2. autofocus
- 현상
HTML autoFocus atrribute를 사용할지 React autoFocus prop을 사용할지 선택하기 위해 각각 어떻게 동작하는지 알아봐야 했다.
- 발견
1) HTML autofocus attribute
- 정적으로 생성되어 DOM에 추가되는 HTML 요소에는 언제나 focus가 들어온다.
- 동적으로 생성되어 DOM에 추가되는 HTML 요소에 autofocus attribute를 지정하면 브라우저에 따라 동작이 제각각이다.
- autofocus attribute가 있는 요소가 유일할 때만 제대로 동작한다.
2) React autofocus prop
- 드문 경우 React 컴포넌트를 앱의 legacy 부분에 렌더링하면 autofocus가 제대로 동작하지 않는다.
- 배운점
autoFocus prop이 제대로 동작하지 않는 이상한 상황이 아니라면 ref를 사용하는 방법보다 autoFocus prop을 사용하는 것이 좋다.
- 선언
autoFocus가 제대로 동작하지 않을 때에만 ref를 사용하여 autoFocus를 동작 시키도록 해야겠다.
3. html-react-parser 라이브러리 사용
- 현상
아래 input 요소의 입력된 값을 변환하는 과정에서 반환 되는 HTML string이 React element로 변환되지 않는 현상이 있었다.
name.replace(..., matched => `<b>${matched}</b>`)
- 발견
replace에서 반환하는 문자열은 HTML 마크업이 포함된 문자열을 문자열로만 반환하기 때문에 원하는 결과가 나오지 않았다.
// parse를 사용하지 않을 때
React.createElement('p', {}, 'Hello, World!')
// parse를 사용할 때
parse('<p>Hello, World!</p>');
html-react-parser 라이브러리를 사용하여 문제를 해결하였다.
parse(name.replace(..., matched => `<b>${matched}</b>`))
- 배운점
html-react-parser 라이브러리의 존재와 사용법을 알게 되었다.
- 선언
필요에 따라 적절한 라이브러리를 잘 사용해야겠다.
4. 디바운스와 제어, 비제어 컴포넌트
- 현상
input field를 useRef를 사용하여 비제어로 관리하였더니 검색 결과가 실패했을 때 출력 되는 값에도 디바운스가 걸리는 현상이 발생했다.
- 발견
input field에 value와 onChange를 추가하여 countries가 필터링 되는 로직 set 디바운스를 걸고 검색 결과가 실패했을 때 출력 되는 디바운스가 걸리지 않게 변경하였다.
- useDebounce 사용
import React from 'react';
import { debounce } from 'lodash';
const useDebounce = (callback, delay) => {
const ref = React.useRef();
React.useEffect(() => {
ref.current = callback;
}, [callback]);
const debouncedCallback = React.useMemo(() => {
const func = () => {
ref.current?.();
};
return debounce(func, delay);
}, []);
return debouncedCallback;
};
export default useDebounce;
- useCallback 사용
import { debounce } from 'lodash';
const debounceFilter = React.useCallback(
debounce(textValue => {
const filtered = countryCode.filter(([, name]) => new RegExp(textValue, 'i').test(name));
setCountries(filtered);
}, 300),
[]
);
- 배운점
단순하게 useRef를 사용해서 Input을 비제어로 관리해도 된다고 생각했는데, 상황에 따라 제어로 관리해야 되는 경우가 있다는 것을 배웠다.
- 선언
코드를 작성할 때 요구 사항과 사용자의 경험을 잘 고려하여 제어, 비제어를 잘 선택할 수 있는 연습을 해야겠다.