seminar-2022 icon indicating copy to clipboard operation
seminar-2022 copied to clipboard

React 과제 2 공통 피드백

Open joongwon opened this issue 2 years ago • 0 comments

2022 React Seminar 과제 2 공통 피드백

DOM 접근

특별한 몇몇 경우가 아닌 이상 getElementById나 기타 방식으로 DOM 객체를 직접 다뤄야 할 일은 별로 없습니다. 99%의 경우 useState로 커버되고, 0.99%는 useRef로 DOM을 얻어올 수 있습니다.

a 요소 (또는 Link 컴포넌트)

어떤 요소를 클릭하면 페이지가 이동하는 경우, aLink로 구현해주시는 게 접근성 면에서 좋습니다. 브라우저가 링크로 인식한다는 점에서 스크린 리더나 브라우저 확장기능과 잘 결합할 수 있고, 커서를 올렸을 때 이동할 링크가 나타난다는 특징도 있습니다.

Controlled input

input 요소의 값이 리액트에서 사용되는 경우 onChangevalue props를 둘 다 사용하여 관리해야 합니다. 예기치 않게 input의 값과 react의 값이 달라지는 경우를 막을 수 있습니다.

사이드이펙트는 useEffect 안에서

함수 컴포넌트 안에는 훅 함수(useState, useEffect 등)를 제외하고는 순수한 동작만 있어야 합니다. 즉, setTimeout으로 타이머를 설정하거나 상태를 변경하는 등 순수하지 않은 코드는 렌더링 중에 실행되어서는 안 됩니다. 그러한 동작은 모두 useEffect 내에서 실행하세요.

function Example() {
  // don't:
  setTimeout(() => {
    alert("100ms 후의 미래");
  }, 100);
  
  // do:
  useEffect(() => {
    setTimeout(() => {
      alert("100ms 후의 미래");
    }, 100);
  }, []);
  
  /* ... */
  return null;
}

enum

  • 0, 1과 같이 단순한 숫자에 특별한 의미를 부여하여 사용하는 경우가 있습니다. 그럴 때에는 각 상수를 const로 이름을 붙여 사용하는 것이 좋습니다.
// 상황 자체는 좋은 예시가 아닙니다. 상수를 선언하여 사용하는 부분에 주목해주세요.
const CANCEL = 0, MODIFY = 1;
setButtonBehavior(CANCEL);

let

이젠 괜히 쓰시는 분 없으리라 생각합니다. 값이 변하지 않는 변수는 언제나 const로 선언해야 합니다.

이름

컴포넌트는 반드시 PascalCase로 써야 하고, 그 외의 javascript에서 쓰는 이름은 99% camelCase로 씁니다. 파일명은 컴포넌트의 경우 export하는 컴포넌트의 이름과 똑같이 쓰고 그 외에는 적당히 camelCase로 지어주시면 됩니다. 아 컨텍스트도 대문자로 시작하게 써주세요.

레이아웃 오류

보통 height 속성을 직접 지정하면 화면 높이가 약간 안 맞아서 스크롤이 생기곤 합니다. flexgrid로 해결하는 게 개인적으로 가장 깔끔하다고 생각하고, 크기를 꼭 직접 지정하고 싶다면 box-sizing: border-box를 사용해보시면 도움이 될 수 있습니다. 아직 레이아웃 잡는 게 힘드시다면 세미나2.5 참고해서 flex랑 grid 써보세요.

key prop

key prop의 기능은 리스트 안의 컴포넌트들을 구분하는 기능 그거 하나뿐입니다. 리스트 밖에서는 사용하면 안 된다는 건 아니지만 동작 면에서도 가독성 면에서도 별다른 기능이 없고 코드 리뷰에 한 줄 추가되는 기능 뿐입니다.

id prop

HTML에서 id는 주로 document.getElementById할 때 많이 쓰게 되는데 리액트에서는 거의 쓸 일이 없습니다. 괜히 id 충돌날 건덕지만 만드는 일이니까 스타일 지정하고 싶다면 className 쓰는 게 좋을 것 같습니다. 저번엔 keyid에 같은 값을 내려주는 코드도 많이 봤는데, 둘은 기능이 전혀 다르니 잘 구분해서 사용하시기 바랍니다.

dependency array

useEffect, useMemo 등등은 두번째 인자로 dependency array를 받습니다. 이걸 그냥 비워놓으신 분들 꽤 있던데 함수 안에서 사용하는 이름은 import로 가져온 거 빼고 전부 넣어준다고 생각하시면 됩니다. 특정 값이 변할 때만 무언가 동작하도록 일부러 빼는 경우도 있을텐데, 그러면 99% 오류 납니다. 그런 건 useEffect 안에서 if 문으로 처리하시면 되구요 아무튼 핵심은 dependency array 잘 넣으시라는 겁니다.

Context를 통한 관심사 분리

React Context의 주요한 기능은 props drilling을 막는 것이지만, state 등을 분리하는 김에 관련된 기능들도 여러 관심사에 따라 분리하고 추상화할 수 있습니다. 예를 들면 메뉴 목록을 state로 만들어 setState와 함께 내려주는 방법도 있지만:

function MenuDataProvider({children}) {
  const [menus, setMenus] = useState([]);
  const [maxId, setMaxId] = useState(4);
  return <MenuDataContext.Provider value={{menus, setMenus, maxId, setMaxId}}>
    {children}
  </MenuDataContext.Provider>;
}

한편으로는 관련된 기능들을 함수로 만들어 내려주는 방법도 있습니다. 이 경우에는 maxId와 같이 사용 방식을 제한된 변수들을 다른 컴포넌트들에게서 숨겨 추상화할 수 있습니다.

function MenuDataProvider({children}) {
  const [menus, setMenus] = useState([]);
  const [maxId, setMaxId] = useState(4);
  const addMenu = useCallback(() => { /* ... */ });
  return <MenuDataContext.Provider value={{menus, addMenu, /* ... */}}>
    {children}
  </MenuDataContext.Provider>;
}

joongwon avatar Nov 04 '22 09:11 joongwon