리액트 함수형 컴포넌트에서 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;
}
불변객체를 사용해야 한다는 것이 중요한 것이다. 느낀점