본문 바로가기
FE/React

useSelector, useDispatch로 리덕스에 편하게 접근해보자

by Jiyoon-park 2022. 1. 23.

문제

상태 관리 라이브러리 리덕스를 사용한다면, 컴포넌트에서 리덕스에 접근하기 위해 세 단계를 거치게 된다.

 

  1. mapStateToProps, mapDispatchToProps를 정의한다.
  2. 정의한 상태값과 액션들을 해당 컴포넌트에 props로 내려준다.
  3. mapStateToProps, mapDispatchToProps를 컴포넌트와 connect로 연결한다.
import React from 'react';
import { connect } from 'react-redux';
​
// 리덕스 상태를 props로
const mapStateToProps = state => ({
  a: state.MyRedux.a,
  b: state.MyRedux.b,
  ...
});
​
// 리덕스 액션을 props로
const mapDispatchToProps = dispatch => ({
  ...MyRedux.actions
});
​
// 리덕스 관련 props를 component와 connect
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MyComponent); 

이런 번거로운 단계를 거치지 않고 컴포넌트 내부에서 리덕스에 바로 접근해서 쏙쏙 꺼내올 순 없을까?

해결방법

험수형 컴포넌트를 사용하고 있다면, useSelector, useDispatch hook을 이용해 쏙쏙 꺼내올 수 있다.

(프로젝트 내 컴포넌트를 클래스형으로 작성하고 있다면, 해당 훅을 사용할 수 없어 그대로 connect를 사용해야한다.)

useSelector와 useDispatch를 사용해서 얼마나 코드가 간단해졌는지 결과부터 확인해보자.

import { useSelector, useDispatch } from 'react-redux'
​
const { a, b } = useSelector(state => ({
  a: state.MyRedux.a,
  b: state.MyRedux.b
}));
​
const dispatch = useDispatch();
const { myReduxActionA, myReduxActionB } = MyRedux.actions;

useSelector

selector 함수를 사용해 Redux store에 원하는 상태값에 접근해 갖고오는 훅
import { useSelector } from 'react-redux'

const result: any = useSelector(selector: Function, equalityFn?: Function)

useSelector를 사용할 때 두번째 파라미터로 값 비교를 해주는 function을 넣어주면, 상태값에 변경이 일어났을 때에만 새롭게 값을 가져오고, 동일한 값일 경우 캐쉬된 값을 사용하게 된다. 이는 컴포넌트의 불필요한 렌더링을 막아주기 때문에 성능 개선에 도움이 되니 아예 custom hook으로 만들어서 쓰는 것도 좋은 방법이 될 수 있을 것 같다. 혹은 Reselect 같은 라이브러리를 사용하는 것도 좋은 방법이다.

useDispatch

Redux store의 액션에 접근해 액션을 실행시켜주는 훅
import { useDispatch } from 'react-redux'
​
const dispatch = useDispatch();

실행을 원하는 곳에서 dispatch(myAction()) 과 같은 형태로 dispatch에 인자로 리덕스의 액션을 넘겨주면 된다. 이 또한 useCallback과 함께 사용하여 불필요한 렌더링을 줄일 수 있다. 

결론

함수형 컴포넌트로 코드를 작성하고 있다면, 컴포넌트에서 리덕스에 접근할 때 useSelector와 useDispatch 훅을 사용해보자. 훨씬 더 간편하게 코드를 작성할 수 있다. 성능개선을 위해 shallow equal을 통해 변화가 일어났을 때만 다시 select해오거나, reselect를 사용하는 것도 좋은 방법이고, useCallback을 통해 dispatch를 메모이제이션 하는 방법도 좋은 방법이다 👍👍👍