TIL : classnames(npm), useState 파라미터, contextAPI/useContext, ref 속성 값

Chanho Yoon·2021년 5월 25일
0

기억보단 기록

목록 보기
3/8

오늘의 기록들

✅ npm classnames

React 라이브러리 중 하나로 className을 적용하는데 있어 다양한 옵션을 사용하여 className을 적용할 수 있다.
true : 클래스 네임 추가(적용)
false : 클래스 네임 삭제(미적용)

삼항 연산자를 사용하는 것보다 훨씬 깔끔하게 작성이 가능하다. 자세한 사항은
classnames에서 확인 가능하다!

&& 논리연산자를 사용해도 삼항연산자보다는 깔끔한 코드를 작성할 수 있지만 클래스 네임이 많을 경우엔 classnames가 더 가독성 좋고 읽기 쉬운 것 같다.

예시

npm install classnames
import cn from 'classnames'
...
<div className = {cn({'tile-show': isTileShow, 'tile-new':isTileNew})} />

✅ 함수형 업데이트 useState 파라미터

const [score, setScore] = useState(0);
const addScore = newTileList.reduce(( acc, item ) => ( item.isMerged ? acc + item.value : acc ), 0);
setScore(addScore);

이와 같이 Setter 함수를 사용할 때 업데이트 하고 싶은 새로운 값을 파라미터로 넣어주게 되는데, 기존 값을 이용해 state를 업데이트를 할 지에 대한 함수를 등록하는 방식으로도 값을 업데이트 할 수 있다.

const [score, setScore] = useState(0);
const addScore = newTileList.reduce(( acc, item ) => ( item.isMerged ? acc + item.value : acc ), 0);
setScore(prevScore => prevScore + addScore)

✨ 함수형 업데이트는 컴포넌트를 최적화할 때 사용하게 된다고 한다.

✅ contextAPI / useContext

기존에 에어비엔비 프로젝트를 진행하며 메인에서 입력한 숙박 날짜와 게스트 정보를 contextAPI를 사용해 headerStore 생성하고 Provider로 전달하여 consumer로 사용하였다.
하지만 render가 아닌 js 작성 부분에서 사용하는 법을 몰랐는데 hook을 이용해 useContext를 사용하면 js 작성 부분에서도 사용할 수 있다고 해서 고쳐보았다.

기존엔 위와 같이 Consumer을 사용했지만 useContext를 사용하면

와 같이 사용가능하다 아주 더 깔끔해졌다!

처음에 에어비엔비 프로젝트를 할 때 상태관리의 필요성을 느끼게 되어 contextAPI를 도입해서 써보다가 단순히 render에서 출력하는 부분에서 사용하는 건 좋았지만 직접 state 값을 받아 다른 로직을 처리할려고 할 땐 방법이 너무 불편해보여서 사용하지 않았었다. useContext를 조금 더 빨리 알았다면.. 부족한 구글링 실력에 반성하는 중..

✨ 기존엔 부모 -> 자식1 -> 자식2이라면 부모 state가 바뀌면 자식1, 자식2 렌더링이 됐지만, contextAPI를 사용하면 부모의 state값이 바뀌었을 때 자식1은 렌더링되지 않고 자식2만 렌더링이 된다. 👍🏻

context store를 종류별로 나누면 얻는 이점

데이터 종류별로 context 나누면 렌더링 성능상 이점이 있다.

context 사용할 때 주의할 점

const [name, setName] = useState('hi');
const [age, setAge] = useState(11);
return (
  <>
    <HeaderStore.Provider value={{ name, age }}>
  </>
)

Provider value에 위와 같이 객체를 입력하게 되면 컴포넌트가 렌더링 될 때마다 매번 새로운 객체가 만들어져 불필요한 렌더링이 발생할 수 있다. 이것을 참조형 데이터를 사용하여 해결이 가능한데

const [user, setUser] = useState({ name: "hi", age: 11});
return (
  <>
    <HeaderStore.Provider value={user}>
  </>
)

매번 새로운 객체가 생성되는게 아니라 기존 객체 내부의 값만 바뀌도록 하면 된다.

✅ ref 속성 값

실제 DOM요소에 직접 접근해야 할 때 사용한다. ex) 포커스, 크기, 스크롤 위치 등

useRef() hook을 사용하면 쉽게 접근할 수 있다.

export default function App() {
  const inputRef = useRef();
  useEffect(() => {
	inputRef.current.focus();
  },[] )
  return (
    <>
      <input type="text" ref={inputRef} />
    </>
}

ref 속성 값은 일반적인 컴포넌트에서도 가능하다.

<ListComponent ref={lcRef} />

클래스형 컴포넌트일 경우엔 해당 컴포넌트의 인스턴스를 가리키게 된다.
함수형 컴포넌트일 경우에는 인스턴스로 만들어지지 않아서 useImperativeHandle hook을 사용하면 된다.

컴포넌트에서 ref 키워드 사용

컴포넌트에서 <BtnBox ref={inputRef} />와 같이 ref를 사용하려면 forwardRef 함수를 사용하면 된다.

ref 속성값 사용 시 주의할 점

컴포넌트가 생성된 이후더라도 ref 객체의 current 속성이 없을 수도 있다.
예를 들어 조건부 렌더링에서 사용된 요소는 렌더링이 되어있지 않다면???
그래서 조건부 렌더링 안의 ref 객체는 current 속성을 검사하는 코드가 필요하다.

<button onClick={() => inputRef.current && inputRef.current.focus()} />

참고
npm classnames
벨로퍼트님 모던 리액트

0개의 댓글