Redux in React

presentational component

필요한 값 또는 함수를 props로만 받아와서 사용하는 컴포넌트
redux를 사용하기 전 컴포넌트의 props를 통해 데이터를 받아오던 방법
어떻게 보여지는지와 관련
UI를 선언하는 것에 집중
props에서 data를 받아와서 사용
data 변경 시에도 props에서 콜백을 호출

container component

redux store의 상태를 조회하거나, action을 dispatch 할 수 있는 컴포넌트
어떻게 동작하는지와 관련
redux의 state에 접근 (useSelector)
data 변경 시 redux action 사용

Redux in React

react 프로젝트에 redux를 적용하기 위해서는 react-redux 라이브러리를 사용해야한다.
설치
npm install react-redux
JavaScript
복사
provider로 store를 넣어서 App을 감싸면 렌더링하는 어떤 컴포넌트던지 redux store에 접근할 수 있게 된다.
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; import rootReducer from './modules'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ); serviceWorker.unregister();
JavaScript
복사
index.js

폴더 구조

Redux hooks

useSelector()

컴포넌트와 state를 연결하는 역할
const itemReducer = useSelector(state => state.itemReducer)
JavaScript
복사

useSelector 최적화

useSelector를 사용해서 redux store의 상태를 조회 시, 상태가 바뀌지 않았으면 리렌더링하지 않음
1.
useSelector 여러번 사용하기
// 최적화 전 - 매번 렌더링 될 때마다 새로운 객체를 만드는 것, 상태 변경 여부를 확인할 수 없어 // 낭비 렌더링이 이루어지고 있음 const { number, diff } = useSelector(state => ({ number: state.counter.number, diff: state.counter.diff })); // 최적화 후 - 값 중 하나라도 바뀌었을 경우 리렌더링 const number = useSelector(state => state.counter.number); const diff = useSelector(state => state.counter.diff);
JavaScript
복사
2.
react-redux의 shallowEqual 함수 useSelector의 두 번째 인자로 전달
import React from 'react'; import { useSelector, useDispatch, shallowEqual } from 'react-redux'; import Counter from '../components/Counter'; import { increase, decrease, setDiff } from '../modules/counter'; function CounterContainer() { // useSelector는 리덕스 스토어의 상태를 조회하는 Hook입니다. // state의 값은 store.getState() 함수를 호출했을 때 나타나는 결과물과 동일합니다. const { number, diff } = useSelector( state => ({ number: state.counter.number, diff: state.counter.diff }), shallowEqual ); (...)
JavaScript
복사
useSelector의 두 번째 파라미터는 equalityFn으로 이전 값과 다음 값을 비교하여 일치하지 않으면 리렌더링한다.
react-redux의 내장함수 shallowEqual는 객체 안의 가장 겉에 있는 값들을 모두 비교해준다.

useDispatch()

action 객체를 reducer로 전달하는 메소드

redux devtools 적용

redux 개발자 도구를 사용하여 현재 store의 상태나 어떤 action이 dispatch 되었는지, state가 어떻게 변화했는지 확인할 수 있다.
크롬 웹 스토어에서 redux devtools 확장 프로그램 설치 및 프로젝트에 redux-devtools-extention을 설치한다.
설치
npm install redux-devtools-extention
JavaScript
복사
import { compose, createStore, applyMiddleware } from "redux"; import rootReducer from '../reducers/index'; import { composeWithDevTools } from 'redux-devtools-extension'; import thunk from "redux-thunk"; const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk))); export default store;
JavaScript
복사
store/store.js
설치하지 않았을 때
import { compose, createStore, applyMiddleware } from "redux"; import rootReducer from '../reducers/index'; import thunk from "redux-thunk"; const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose; const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk))); export default store;
JavaScript
복사
store/store.js
리덕스 어떻게 써야 잘 썼다고 소문이 날까?