useSelector에 대해 궁금증이 하나 생겨서 이런저런 실행을 해보다가 실행 횟수에 대해서 알게되었습니다.
1. action이 dispatch 되어서
- useSelector마다 redux store를 sbuscribe 하기 때문에 action이 dispatch 될 때마다
selector는 항상 실행
된다.
useSelector()
will also subscribe to the Redux store, and run your selector whenever an action is dispatched.
출처 - https://react-redux.js.org/api/hooks#useselector
2. 렌더링 시 store가 달라져서
1번에서 selector의 return값이 달라지면 useSelector를 사용하는 컴포넌트는 re-render하게 된다. 이렇게 re-render 할 때 selector는 이전 rendering 할 때의 store가 현재와 다르므로 selector를 실행
한다.
The selector will be called with the entire Redux store state as its only argument. The selector will be run whenever the function component renders (unless its reference hasn’t changed since a previous render of the component so that a cached result can be returned by the hook without re-running the selector).
출처 - https://react-redux.js.org/api/hooks#useselector
3. StricMode로 렌더링이 한번 더 되어서
<React.StrictMode>
를 사용하면 렌더링이 강제로 두 번 되기 때문에 위 2번 항목에서 설명한 일이 다시 한번 일어난다.
실행 회수에 따른 상황
distpatch에 따라 selector가 실행되는 횟수에 따른 상황을 정리하자면
- 1회 : selector가 실행되었지만 이전 값과 동일해서 해당 component가 다시 rendering 할 필요 없는 경우
- 2회 : selector를 실행하고 보니 값이 달라져서 해당 component를 다시 rendering 해야 하는 경우
- 3회 : 2회의 경우에서
<React.StrictMode>
를 사용한 경우
Tip
위 경우와 무관하지만 redux store가 변경되지 않은 상태에서 다른 state변경으로 인해 rendering이 다시 되는 상황에서 selector가 불필요하게 다시 실행되지 않게 하려면 실행 회수를 줄이려면 다음과 같이 useSelector호출할 때 함수를 생성하지 말고 useCallback을 이용하거나 selector 함수를 컴포넌트 밖에서 선언하고 그를 참조하여 사용해야 한다. (하지만 selector가 단순하다면 한번 더 실행되는 것은 성능에 영향이 거의 없다. 그래서 전 자주 그냥… )
useSelector( s => s.count );