useState 올바르게 사용하기
💡 state란?
필자는 이전까지, 그냥
state
는 자주 변동되는 값을 담는 그릇이라고만 생각해왔었다.
하지만, React를 계속 사용하다 보니 state
에 대한 피상적 이해만으로는 React를 깊게 이해하고 개발을 하는데 무리가 있다는 판단이 들어 state
를 다시 정리해보고자 한다.
state의 정의
state
는 값이 계속 변경되는 동적 데이터로, 컴포넌트 간의 상호작용을 담당하기도 한다. 또한,state
의 값이 변경되면 컴포넌트는 리렌더링 된다.
state가 되기 위한 조건
우선, 모든 학습에 앞서 state
가 무엇인지에 대한 명확한 이해가 필요하다..!!
그렇다면 state
란 무엇일까? 아래의 질문들에 직접 답변을 해보자 (해당 질문에 state가 포함 되는지).
state
데이터가 계속 변동되는가?- 부모로부터 전달 받은
props
인가? - 특정
state
로부터 어떠한 계산을 통해 도출되는 데이터인가?
결론부터 얘기하자면 정답은 OXX다.
state
는 정적 데이터가 아닌, 동적 데이터다. 따라서 변하지 않고 고정된 데이터를state
로 활용하는 것은 옳지 않다. 정적 데이터는const
에 상수로써 담아 활용하는 것이 옳다고 할 수 있다.부모로부터 전달 받은
props
는props
일 뿐이다.state
는 하나의 컴포넌트 안에서 관리되는 데이터로,state
를 사용할 때는 관리 및 사용하는 컴포넌트(부모)와 이를 활용하는 컴포넌트(props로 받아 활용하는 자식 컴포넌트)로 철저히 분리하여 사용해야 한다.우리는 중복배제 원칙을 항상 생각하며
state
의 최소집합을 고려해야 한다. 아래의 예시를 보자.1
2const [todos, setTodos] = useState([]);
const [todoCount, setTodoCount] = useState(0);이는 효율적이지 못한
state
활용 방식이다. 굳이todoCount
라는state
를 생성하지 않아도 우리는todos.length
등을 활용해 해당 값을 언제든지 구할 수 있다. 그냥 아래와 같이 꼭 필요한state
만 활용해보는게 어떨까? 불필요한 리렌더링을 방지하자!1
2const [todos, setTodos] = useState([]);
const todoCount = todos.length;
🤷🏻♂️ state와 props의 차이점
props
는 property의 줄임말로,state
와 언뜻 보기에는 비슷하지만 분명한 차이점을 보유한다.
물론state
와 동일하게props
가 변경되면 컴포넌트는 리렌더링 된다.
props
는 컴포넌트 간에 전달되는 데이터다.즉, 함수 안의 매개변수, 인자와 같은 역할을 하는 것이다. 반면,
state
는 함수 안에서만 활용되는 ‘함수레벨 스코프’의 변수이자 Javascript 객체와 같다고 볼 수 있다.props
는 변경될 수 없다.state
는setState
를 통해 컴포넌트 내에서 언제든지 변경될 수 있다. 하지만props
는 ‘읽기 전용’으로, 참조만 할 뿐 직접적으로 이를 변경할 수는 없다. 위에서 설명한 관리자 vs 사용자가 명백히 구분되어 있다는 것이 이를 의미한다.
✨ useState를 올바르게 사용하는 방법
state
를 통해 계산될 수 있는 값은 굳이useState()
에 담지 않아도 된다.위에서 설명했듯, 기존의
state
를 통해 계산될 수 있는 값이라면, 그냥 상수 또는 변수로써만 사용해도 충분하다.setState()
가useEffect
내에서 비동기적으로 사용될 경우,state
로 사용하지 않는다.굉장히 중요한 진리와도 같은 제언이다. 아래의 예시를 봐보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const [product, setProduct] = useState(null);
const [price, setPrice] = useState(null);
useEffect(() => {
const fetcher = async () => {
const result = getProduct();
setProduct(result);
};
fetcher();
}, []);
useEffect(() => {
if (product) {
setPrice(getPrice(product));
return;
}
}, [product]);이 경우,
useEffect
가 두 번 쓰였다. 컴포넌트가 렌더링 됐을 때product
를utils
의 유틸함수에서 받아오고,product
가 존재하면setPrice
를 통해price
가 업데이트 된다.근데… 그냥 이렇게 사용하면 되지 않을까?
1
2
3
4
5
6
7
8
9
10const [product, setProduct] = useState(null);
const price = product && getPrice(product);
useEffect(() => {
const fetcher = async () => {
const result = getProduct();
setProduct(result);
};
fetcher();
}, []);즉 이는 위에서 설명한 1번 조건과도 연결이 되는 것이다.
product
라는state
의 유무에 따라price
값이 정해져야 하는 것인데, 이는 충분히product
라는state
하나만으로도 구현할 수 있기에 굳이price
라는state
를 하나 더 만들 필요가 없는 것이다.
포스팅에 참고한 자료
react-guide/props-vs-state.md at master · uberVU/react-guide
Lucy | ReactJS: Props vs. State
useState 올바르게 사용하기