리액트 함수형 컴포넌트에서 useState를 통해 상태관리를 할때, 고민되었던 부분이었는데
useState in React: A complete guide 글의 Multiple state variables or one state object
부분에서 다루고 있었다.
연관된 값의 상태를 다룰때, 두가지 방법이 있다.
첫째, id, message, author
를 각각 상태변수로 관리하기,
둘째, {id, message, author}
객체로 하나의 상태변수로 관리하기
// multiple state variables:
const [id, setId] = useState(-1);
const [message, setMessage] = useState('');
const [author, setAuthor] = useState('');
// object state variable:
const [messageObj, setMessage] = useState({
id: 1,
message: '',
author: ''
});
위 글에서는 복잡한 중첩구조를 가진 객체를 사용할 때는, 복사비용에 주의하라고 하며
immutable.js
, immer
)사용방법을 추천했다.
1번에서 추천한 리액트 공식문서를 살펴보자.
클래스형 컴포넌트에서 함수형컴포넌트로 변경할때,
모든 상태를 useState()의 하나의 객체안에 담아 사용하는 경우가 있다.
function Box() {
const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 });
// ...
}
상태를 변경할 때는 다음과 같이 할 것이다.
useEffect(() => {
function handleWindowMouseMove(e) {
// Spreading "...state" ensures we don't "lose" width and height
setState(state => ({ ...state, left: e.pageX, top: e.pageY }));
}
// Note: this implementation is a bit simplified
window.addEventListener('mousemove', handleWindowMouseMove);
return () => window.removeEventListener('mousemove', handleWindowMouseMove);
}, []);
useState에서는 상태가 업데이트 될때, class형처럼 merge되지 않고, replace되기 때문에 ...state로 기존값을 적용하고, 변경값만 업데이트한다.
객체 상태를 merge하기 위해 useLegacyState
라는 커스텀 훅을 사용할 수 있지만, 같이 변경되는 값들 기준으로 상태변수를 분리하는 것을 추천한다.
위 예시에서 left, top 값만 변경되므로 이 값은 position 객체로 분리하면 merge필요없이 항상 replace하여 사용할 수 있다.
function Box() {
const [position, setPosition] = useState({ left: 0, top: 0 });
const [size, setSize] = useState({ width: 100, height: 100 });
useEffect(() => {
function handleWindowMouseMove(e) {
setPosition({ left: e.pageX, top: e.pageY });
}
// ...
이렇게 독립적인 상태변수를 분리하는것은 또다른 장점이 있다. 추후 커스텀훅으로 관련 로직을 추출하기 더 쉬워진다.
function Box() {
const position = useWindowPosition();
const [size, setSize] = useState({ width: 100, height: 100 });
// ...
}
function useWindowPosition() {
const [position, setPosition] = useState({ left: 0, top: 0 });
useEffect(() => {
// ...
}, []);
return position;
}
불변객체
를 사용해야 한다는 것이 중요한 것이다. 느낀점