seminar-2022
seminar-2022 copied to clipboard
React 과제 2 공통 피드백
2022 React Seminar 과제 2 공통 피드백
DOM 접근
특별한 몇몇 경우가 아닌 이상 getElementById
나 기타 방식으로 DOM 객체를 직접 다뤄야 할 일은 별로 없습니다. 99%의 경우 useState
로 커버되고, 0.99%는 useRef
로 DOM을 얻어올 수 있습니다.
a
요소 (또는 Link
컴포넌트)
어떤 요소를 클릭하면 페이지가 이동하는 경우, a
나 Link
로 구현해주시는 게 접근성 면에서 좋습니다. 브라우저가 링크로 인식한다는 점에서 스크린 리더나 브라우저 확장기능과 잘 결합할 수 있고, 커서를 올렸을 때 이동할 링크가 나타난다는 특징도 있습니다.
Controlled input
input 요소의 값이 리액트에서 사용되는 경우 onChange
와 value
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
속성을 직접 지정하면 화면 높이가 약간 안 맞아서 스크롤이 생기곤 합니다. flex
나 grid
로 해결하는 게 개인적으로 가장 깔끔하다고 생각하고, 크기를 꼭 직접 지정하고 싶다면 box-sizing: border-box
를 사용해보시면 도움이 될 수 있습니다. 아직 레이아웃 잡는 게 힘드시다면 세미나2.5 참고해서 flex랑 grid 써보세요.
key
prop
key
prop의 기능은 리스트 안의 컴포넌트들을 구분하는 기능 그거 하나뿐입니다. 리스트 밖에서는 사용하면 안 된다는 건 아니지만 동작 면에서도 가독성 면에서도 별다른 기능이 없고 코드 리뷰에 한 줄 추가되는 기능 뿐입니다.
id
prop
HTML에서 id
는 주로 document.getElementById
할 때 많이 쓰게 되는데 리액트에서는 거의 쓸 일이 없습니다. 괜히 id
충돌날 건덕지만 만드는 일이니까 스타일 지정하고 싶다면 className
쓰는 게 좋을 것 같습니다. 저번엔 key
랑 id
에 같은 값을 내려주는 코드도 많이 봤는데, 둘은 기능이 전혀 다르니 잘 구분해서 사용하시기 바랍니다.
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>;
}