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 올바르게 사용하기