Context API
프로젝트의 상태, 함수, 외부 라이브러리 인스턴스, DOM까지도 관리 가능
- 새로운 Context 생성
const UserDispatch = React.createContext(null);
- Context를 만들면 안에 들어있는 Provider라는 컴포넌트로 Context의 값을 정할 수 있음.
컴포넌트 사용 시 value라는 값을 설정해주면 됨.
<UserDispatch.Provider value={dispatch}>…</UserDispatch.Provider>
=> Provider로 감싸진 컴포넌트 전역에서 Context 값을 조회하고 사용 가능
export const UserDispatch = React.createContext(null);
로 내보내주면 나중에 사용하고 싶을 때
import React, { useContext } from 'react';
import { UserDispatch } from ‘./App’;
...
const dispatch = useContext(UserDispatch);
...
<button
onClick={() => {
dispatch({ type: 'REMOVE_USER', id: user.id });
}}>삭제</button>
처럼 불러와서 사용 가능 (위의 예시에서는 내보낸 파일 위치에서 useReducer 및 reducer 함수에서 switch로 분기한 설정을 사용 중)
Immer
리액트에서 배열이나 객체 업데이트 시 직접 수정 X. 불변성 지켜주면서 업데이트 해줘야 함
- 객체: spread 연산자 사용
- 배열: concat, filter, map 등의 함수 사용 (ex. push, splice 등 사용한 항목 직접 수정 X)
데이터 구조가 까다로워지면 불변성 지키면서 새로운 데이터 생성하는 코드가 복잡해짐
=> Immer 라이브러리 쓰면 상태 업데이트 할 때 Immer가 불변성 관리 대신 해줌
- 라이브러리 설치 후 선언 필요
yarn add immer
import produce from ‘immer’;
- produce 함수 사용 시)
첫번째 파라미터: 수정하고 싶은 상태
두번째 파라미터: 어떻게 업데이트 할지 정의하는 함수
- 함수형 업데이트를 하는 경우에도 Immer 사용하면 편리
- produce 함수에 파라미터 2개 넣으면: 첫번째 파라미터에 넣은 상태 불변성 유지하면서 새로운 상태 만들어줌.
첫번째 파라미터 생략하고 파라미터로 업데이트 함수만 넣으면: 상태 업데이트 해주는 함수가 반환값이 됨.
- 단, 사용하면 간단해지기도 하지만 오히려 코드가 길어질 때도 있음.
- 성능적으로는 Immer를 사용하지 않은 코드가 조금 더 빠름.
- JavaScript 엔진의 proxy 기능을 사용하는데, 구형브라우저나 react-native 환경에서는 지원 X
=> ES5 fallback 사용하게 되는데 이게 꽤나 느려짐
∴ 가능하면 데이터의 구조가 복잡해지게 되는 것을 방지하기. 무조건 사용하지는 말고 '어쩔 수 없을 때' 사용하기
예시 코드 1)
const state = {
number: 1,
dontChangeMe: 2
};
const nextState = produce(state, draft => {
draft.number += 1;
});
예시 코드 2)
const nextState = produce(state, draft => {
const post = draft.posts.find(post => post.id === 1);
post.comments.push({
id: 3,
text: ‘쉬운 추가’
});
});
↓ Immer를 사용하지 않은 코드와 비교
불변성을 지키기 위한 노력이 필요
const nextState = {
...state,
posts: state.posts.map(post =>
post.id === 1
? {
...post,
comments: post.comments.concat({
id: 3,
text: '새로운 댓글'
})
}
: post
)
};
- 유저를 삭제하는 코드로 비교해보기
Immer 미사용 - 선택한 유저만 제외해서 필터링
return {
...state,
users: state.users.filter(user => user.id !== action.id)
};
Immer 사용 - 선택한 유저의 인덱스를 받아와 삭제
return produce(state, draft => {
const index = draft.users.findIndex(user => user.id === action.id);
draft.users.splice(index, 1);
})
'React' 카테고리의 다른 글
[React] react-router-dom v6 에서 Hooks 사용하기 (0) | 2022.07.22 |
---|---|
[React 공부] 클래스형 컴포넌트 (0) | 2022.07.05 |
[React 공부] 함수형 컴포넌트의 Hooks (0) | 2022.07.05 |