맨땅헤딩! 2023. 5. 10. 09:38

해당 포스트는 제로베이스 오프라인스쿨 진행 과정 중 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을 비제어로 관리해도 된다고 생각했는데, 상황에 따라 제어로 관리해야 되는 경우가 있다는 것을 배웠다.

   

- 선언

코드를 작성할 때 요구 사항과 사용자의 경험을 잘 고려하여 제어, 비제어를 잘 선택할 수 있는 연습을 해야겠다.