아래 내용들은 빠르게 Redux를 사용하기 위해 핵심 부분만 정리해놓은 글이다. 필요한 부분만 쏙속 찾아서 보면 된다.

combineReducers 사용해서 rootReducer 만들어주기connect 함수 사용해서 컴포넌트와 리덕스 연동하기Reducer 함수 만들기const ACTIONE_NAME = "module_name/ACTION_NAME";
export const action = () => ({ type : ACTION_NAME });
or
import { createAction } from 'redux-actions'
export const action = createAction(ACTION_NAME);
파라미터가 존재하는 경우
export const action = createAction(ACTION_NAME, data => data);
// 이 작업이 필수는 아니며 생략해도 동일하게 작동
// 다만 넣어주는 것이 가독성이 좋아진다.
// 함수가 어떤 파라미터를 필요로 하는지 파악할 수 있다.
결과는 아래처럼 나온다.
{
type : ACTION_NAME,
payload : data
}
const initialState = {
number : 0
}
아래 4가지 조건 만족
function reducer(state = initialState, action) {
switch (action.type) {
case ACTION_NAME:
return {
...
};
default:
return state;
}
}
or
import { handleActions } from 'redux-actions';
(...)
const reducer = handleActions({
[ACTION_NAME] : (state, action) => ({
...
})
);
// 파라미터가 존재하는 경우
const reducer = handleActions({
[ACTION_NAME] : (state, {payload : data}) => ({
...
})
);
moduels/index.js
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
reducer1,
reducer2,
});
export default rootReducer;
src/index.js
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from './modules';
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
dev-tool 연결 하려면
import { composeWithDevTools } from "redux-devtools-extension";
const store = createStore(rootReducer, composeWithDevTools());
Redux와 연동하기 위해서는 connect 함수를 사용해야 한다.
connect(mapStateToProps, mapDispatchToProps)(연동하고싶은 컴포넌트)
mapStateToProps는 Store에 담긴 값을 받아서 Props로 변환시켜주는 역할을, mapDispatchToProps는 Action을 Props에 담는 역할을 한다.
mapStateToProps
const mapStateToProps = state => ({
data: state.counter.number
});
mapDispatchToProps
import { action } from "../modules/something";
const mapDispatchToProps = dispatch => ({
action_name: () => dispatch(action())
});
or
import { bindActionCreators } from 'redux'
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
action1,
action2
},
dispatch
);
Container
const SomeContainer = ({ data, action }) => {
return (
<Some number={data} onChange={action} />
);
};
export default connect(mapStateToProps, mapDispatchToProps)(SomeContainer);
useSelector
const result = useSelector(상태 선택 함수);
import {useSelector} from 'react-redux';
(...)
const SomeContainer = () => {
const data = useSelector(state => state.some.number)
return (
<Some number={data}/>
);
};
useDispatch
const dispatch = useDispatch();
import React, {useCallback} from "react";
(...)
const SomeContainer = () => {
const dispatch = useDispatch();
const onClick = useCallback(() => dispatch(click()), [dispatch]);
// 파라미터 존재하는 경우
const onChange = useCallback((input) => dispatch(change()), [dispatch]);
return (
<Some
onClick={onClick}
onChange={onChange}
/>
);
};
useAction
lib/useActions.js
import { bindActionCreators } from 'redux'
import { useDispatch } from 'react-redux'
import { useMemo } from 'react'
export function useActions(actions, deps) {
const dispatch = useDispatch()
return useMemo(
() => {
if (Array.isArray(actions)) {
return actions.map(a => bindActionCreators(a, dispatch))
}
return bindActionCreators(actions, dispatch)
},
deps ? [dispatch, ...deps] : [dispatch]
)
}
첫 번째 파라미터 : 액션 생성 함수로 이루어진 배열
두 번째 파라미터 : 이 배열 안에 원소가 바뀌면 액션 다시 디스패치
import useActions from '../lib/useActions'
(...)
const SomeContainer = () => {
const [onClick, onChange] = useActions(
[click, change],
[]
);
return (
<Some
onClick={onClick}
onChange={onChange}
/>
);
};
connect 함수의 경우 props가 바뀔때만 렌더링을 다시 하지만 useSelector는 아니므로 React.memo(SomeContainer) 사용해서 최적화 해주기
export default React.memo(SomeContainer);
다만 React.memo를 항상 사용하는 것이 능사는 아니다. React.memo를 사용해야 하는 경우는 다음과 같은 경우다.
1. 순수 함수 컴포넌트
2. 자주 렌더링을 해야하는 함수
3. 같은 props로 자주 리 렌더링 되는 함수
4. 컴포넌트가 props 비교를 필요로 하는 많은 UI 요소를 가지고 있는 경우
만약 props가 자주 변동되는 환경이라면 React.memo를 사용한다고 해도 컴포넌트를 다시 렌더링 해야하므로 불필요한 비교 과정만 추가하는 꼴이다! 현명하게 사용하자.
잘 봤습니당 ㅎㅎ React.memo는 무조건 하는게 좋을까요? 별로 비교가 필요 없을 경우에는 memo를 하면 오히려 비교한다고 성능이 안 좋아진다고도 봤어가지구요 ㅎㅎ.