[React] Redux μ‚¬μš©

✨ 강은비·2022λ…„ 1μ›” 19일
0

React

λͺ©λ‘ 보기
23/36

react μŠ€ν„°λ””μ—μ„œ λ¦¬μ•‘νŠΈλ₯Ό λ‹€λ£¨λŠ” κΈ°μˆ μ΄λΌλŠ” 책을 μ„ μ •ν–ˆκ³  이 책을 읽고 배운 것을 λ°”νƒ•μœΌλ‘œ μž‘μ„±λ˜μ—ˆλ‹€.


πŸ“Œ Redux μ‚¬μš©ν•˜κΈ°

  • λ¦¬λ•μŠ€λ₯Ό μ‚¬μš©ν•  λ•Œ μ»΄ν¬λ„ŒνŠΈλ₯Ό Presentational Component와 Container Component둜 κ΅¬λΆ„ν•˜μ—¬ μž‘μ„±ν•œλ‹€.
    • Presentational Component: 주둜 μƒνƒœ 관리가 이루어지지 μ•Šκ³ , κ·Έμ € props둜 μƒνƒœλ₯Ό 받아와 μ˜¨μ „νžˆ 뷰만 λ‹΄λ‹Ήν•˜λŠ” μ»΄ν¬λ„ŒνŠΈ
    • Container Component: λ¦¬λ•μŠ€μ™€ μ—°λ™λ˜μ–΄ μžˆλŠ” μ»΄ν¬λ„ŒνŠΈλ‘œ, μƒνƒœ μ—…λ°μ΄νŠΈ 둜직이 μ‘΄μž¬ν•œλ‹€.

μ΄μ œλŠ” Presentational Component와 Container Componentλ₯Ό λΆ„λ¦¬ν•˜λŠ” 것을 더 이상 ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.Hook을 ν†΅ν•΄μ„œ μƒνƒœ κ΄€λ ¨ λ‘œμ§μ„ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λΆ„λ¦¬μ‹œν‚¬ 수 있기 λ•Œλ¬Έμ— 더 이상 μ»΄ν¬λ„ŒνŠΈμ˜ ꡬ뢄이 λΆˆν•„μš”ν•΄μ‘Œλ‹€.


✨ μ•‘μ…˜ νƒ€μž… μ •μ˜ν•˜κΈ°

  • μ•‘μ…˜ κ°μ²΄λŠ” λ°˜λ“œμ‹œ type ν”„λ‘œνΌν‹°λ₯Ό κ°€μ Έμ•Ό ν•˜κΈ° λ•Œλ¬Έμ— μ•‘μ…˜ νƒ€μž…μ„ μ •ν•΄μ•Ό ν•œλ‹€.
  • λͺ¨λ“ˆμ΄λ¦„/μ•‘μ…˜μ΄λ¦„κ³Ό 같은 ν˜•νƒœλ‘œ μ •μ˜ν•΄μ•Ό μ€‘λ³΅λ˜λŠ” 일이 λ°œμƒν•˜μ§€ μ•Šλ„λ‘ ν•œλ‹€.
const INCREASE = "counter/INCREASE";

✨ μ•‘μ…˜ 생성 ν•¨μˆ˜ λ§Œλ“€κΈ°

export const increase = () => ({type: "INCREASE"});
  • λ§Œμ•½ μ•‘μ…˜ 객체 내에 typeμ™Έμ˜ μΆ”κ°€ 정보가 ν•„μš”λ‘œ ν•  λ•ŒλŠ” μ•‘μ…˜ 생성 ν•¨μˆ˜μ˜ 인자둜 μ „λ‹¬ν•˜μ—¬ ν•΄λ‹Ή 정보λ₯Ό 담은 μ•‘μ…˜ 객체λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ ν•œλ‹€.

❗ redux-actions

  • createAction
    • ν•„μˆ˜ 인자둜 μ•‘μ…˜ νƒ€μž…μ„ μ „λ‹¬ν•œλ‹€.
    • μ•‘μ…˜ 객체 내에 μΆ”κ°€ λ°μ΄ν„°λŠ” payloadλΌλŠ” ν”„λ‘œνΌν‹°λ‘œ μ •μ˜λœλ‹€.
    • μ•‘μ…˜ 생성 ν•¨μˆ˜μ—μ„œ λ°›μ•„ 온 인자λ₯Ό κ·ΈλŒ€λ‘œ payload에 λ„£λŠ” 것이 μ•„λ‹ˆλΌ λ³€ν˜•μ„ μ£Όμ–΄μ„œ λ„£κ³  μ‹Άλ‹€λ©΄, 두 번째 인자둜 payloadλ₯Ό μ •μ˜ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ „λ‹¬ν•˜λ©΄ λœλ‹€.
    • 맀번 객체λ₯Ό 직접 λ§Œλ“€μ–΄ 쀄 ν•„μš” 없이 κ°„λ‹¨ν•˜κ³  짧은 μ½”λ“œλ‘œ μ•‘μ…˜ 생성 ν•¨μˆ˜λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.
  • handleActions
    • 첫 번째 인자둜 각 앑선에 λŒ€ν•œ μ—…λ°μ΄νŠΈ ν•¨μˆ˜λ₯Ό 담은 객체λ₯Ό μ „λ‹¬ν•˜κ³ , 두 번째 인자둜 초기 μƒνƒœλ₯Ό μ „λ‹¬ν•œλ‹€.
    • μ΄λ•Œ μ—…λ°μ΄νŠΈ ν•¨μˆ˜λŠ” ν˜„μž¬ μƒνƒœμ™€ μ•‘μ…˜ 객체λ₯Ό 인자둜 λ°›λŠ”λ‹€.

❗ immer

  • λ¦¬λ“€μ„œ ν•¨μˆ˜μ—μ„œ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈλ₯Ό ν•  λ•Œ κΈ°μ‘΄ μƒνƒœμ˜ λΆˆλ³€μ„±μ„ μ§€μΌœμ•Ό ν•œλ‹€.
  • ν•˜μ§€λ§Œ λ§Žμ€ 객체가 μ€‘μ²©λ˜κ³  ꡬ쑰가 λ³΅μž‘ν•œ 객체일수둝 λΆˆλ³€μ„±μ„ 지킀기 μ–΄λ ΅κΈ° λ•Œλ¬Έμ— immer 라이브러리λ₯Ό μ‚¬μš©ν•˜λ©΄ νŽΈλ¦¬ν•˜κ²Œ λΆˆλ³€μ„±μ„ μœ μ§€ν•˜λ©° μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•  수 μžˆλ‹€.
  • produce
    • 첫번째 인자둜 μˆ˜μ •ν•˜κ³  싢은 μƒνƒœλ₯Ό λ°›κ³ , λ‘λ²ˆμ§Έ 인자둜 μ–΄λ–»κ²Œ μ—…λ°μ΄νŠΈν• μ§€ μ •μ˜ν•œ ν•¨μˆ˜λ₯Ό λ°›λŠ”λ‹€.
    • 두 번째 인자둜 받은 ν•¨μˆ˜ λ‚΄μ—μ„œ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ”λ° λΆˆλ³€μ„±μ„ 지킀지 μ•Šμ•„λ„ λœλ‹€.
    • λŒ€μ‹  produceν•¨μˆ˜κ°€ λΆˆλ³€μ„±μ„ μ§€μΌœμ£Όκ³  μƒˆλ‘œμš΄ μƒνƒœλ₯Ό λ°˜ν™˜ν•œλ‹€.

✨ 루트 λ¦¬λ“€μ„œ

  • createStore ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€ν† μ–΄λ₯Ό λ§Œλ“€ λ•ŒλŠ” ν•˜λ‚˜μ˜ λ¦¬λ“€μ„œλ§Œ μ‚¬μš©ν•΄μ•Ό ν•˜κ³ , ν•œ ν”„λ‘œμ νŠΈ 내에선 ν•˜λ‚˜μ˜ μŠ€ν† μ–΄λ§Œ μ‘΄μž¬ν•΄μ•Ό ν•˜λ―€λ‘œ μ—¬λŸ¬ λ¦¬λ“€μ„œκ°€ μ‘΄μž¬ν•  λ•ŒλŠ” 루트 λ¦¬λ“€μ„œλ₯Ό λ§Œλ“ λ‹€.
  • λ¦¬λ•μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” combineReducersν•¨μˆ˜λ₯Ό μ΄μš©ν•œλ‹€.
// modules/index.js
const rootReducer = combineReducers({
    counter,
    todos
});

export default rootReducer;

✨ μŠ€ν† μ–΄ λ§Œλ“€κΈ° 및 λ¦¬λ•μŠ€ 적용

  • μŠ€ν† μ–΄λ₯Ό λ§Œλ“€ λ•Œ createStore ν•¨μˆ˜μ˜ 인자둜 rootReducerλ₯Ό μ „λ‹¬ν•œλ‹€.
  • μ»΄ν¬λ„ŒνŠΈμ—μ„œ μŠ€ν† μ–΄λ₯Ό μ‚¬μš©ν•  수 μžˆλ„λ‘ μ΅œμƒμœ„ μ»΄ν¬λ„ŒνŠΈμΈ App을 react-reduxμ—μ„œ μ œκ³΅ν•˜λŠ” Provider μ»΄ν¬λ„ŒνŠΈλ‘œ 감싼닀.
  • μ΄λ•Œ Provider μ»΄ν¬λ„ŒνŠΈμ˜ store props둜 μ•žμ„œ λ§Œλ“  storeλ₯Ό μ „λ‹¬ν•œλ‹€.
// src/index.js
import { createStore } from "redux";
import rootReducer from "./modules";
import {Provider} from "react-redux";

const store = createStore(rootReducer);

ReactDOM.render(
    <Provider store={store}>
    	<App/>
    </Provider>
    ...
);

πŸ“Œ μ»΄ν¬λ„ŒνŠΈμ—μ„œ Redux μ‚¬μš©

이제 μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ¦¬λ•μŠ€ μŠ€ν† μ–΄μ— μ ‘κ·Όν•˜μ—¬ μ›ν•˜λŠ” μƒνƒœλ₯Ό λ°›μ•„μ˜€κ³  μ•‘μ…˜λ„ dispatchν•˜λ„λ‘ ν•œλ‹€.

✨ connect ν•¨μˆ˜

connect(mapStateToProps, mapDispatchToPros)(연동할 μ»΄ν¬λ„ŒνŠΈ)

  • mapStateToProps
    • λ¦¬λ•μŠ€ μŠ€ν† μ–΄ μ•ˆμ˜ μƒνƒœλ₯Ό μ‘°νšŒν•΄ μ–΄λ–€ 것을 μ»΄ν¬λ„ŒνŠΈμ˜ props둜 전달할지 μ •μ˜ν•˜λŠ” ν•¨μˆ˜
    • λ¦¬λ•μŠ€ μŠ€ν† μ–΄μ— μžˆλŠ” μƒνƒœλ₯Ό 인자둜 λ°›λŠ”λ‹€.
  • mapDispatchToProps
    • μ•‘μ…˜μ„ dispatchν•˜λŠ” ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄μ„œ μ»΄ν¬λ„ŒνŠΈμ˜props둜 μ „λ‹¬ν•˜λŠ” ν•¨μˆ˜
    • μŠ€ν† μ–΄μ˜ λ‚΄μž₯ ν•¨μˆ˜μΈ dispatch ν•¨μˆ˜λ₯Ό 인자둜 λ°›λŠ”λ‹€.
  • mapStateToProps와 mapDispatchToPropsκ°€ λ°˜ν™˜ν•˜λŠ” 객체 λ‚΄λΆ€μ˜ 값듀은 μ „λΆ€ μ»΄ν¬λ„ŒνŠΈμ˜ props둜 μ „λ‹¬λœλ‹€.
  • mapDispatchToProps에 ν•΄λ‹Ήν•˜λŠ” 인자둜 ν•¨μˆ˜ ν˜•νƒœκ°€ μ•„λ‹Œ μ•‘μ…˜ 생성 ν•¨μˆ˜λ‘œ 이루어진 객체 ν˜•νƒœλ₯Ό 전달해도 λœλ‹€.
  • connectν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ 또 λ‹€λ₯Έ ν•¨μˆ˜κ°€ λ°˜ν™˜λ˜κ³  이 ν•¨μˆ˜μ˜ 인자둜 μ»΄ν¬λ„ŒνŠΈλ₯Ό μ „λ‹¬ν•˜λ©΄ λ¦¬λ•μŠ€μ™€ μ—°λ™λœ μ»΄ν¬λ„ŒνŠΈκ°€ λ°˜ν™˜λœλ‹€.

✨ useSelector

const result : any = useSelector(selector : Function, deps : any[])
  • useSelectorλŠ” λ¦¬λ•μŠ€ μŠ€ν† μ–΄μ— μžˆλŠ” μƒνƒœλ₯Ό μ‘°νšŒν•  λ•Œ μ‚¬μš©λœλ‹€.
  • useSelectrorλŠ” 인자둜 selector ν•¨μˆ˜μ™€ deps 배열을 λ°›λŠ”λ‹€.
    • selector ν•¨μˆ˜λŠ” 인자둜 λ¦¬λ•μŠ€ μŠ€ν† μ–΄μ— μžˆλŠ” μƒνƒœλ₯Ό λ°›κ³  μ–΄λ–€ μƒνƒœκ°’μ„ λ°˜ν™˜ν• μ§€ μ •μ˜ν•œλ‹€.
    • deps 배열은 μ–΄λ–€ 값이 λ°”λ€Œμ—ˆμ„ λ•Œ selector ν•¨μˆ˜λ₯Ό μž¬μ •μ˜ν• μ§€ μ„€μ •ν•œλ‹€.
    • μƒλž΅ν•˜λ©΄ λ Œλ”λ§λ  λ•Œλ§ˆλ‹€ selector ν•¨μˆ˜λ₯Ό μž¬μ •μ˜ν•œλ‹€.
const number = useSelector(state => state.counter.number, []);

✨ useDispatch

  • useDispatchλ₯Ό ν˜ΈμΆœν•˜λ©΄ μŠ€ν† μ–΄μ˜ λ‚΄μž₯ν•¨μˆ˜ dispatchλ₯Ό λ°˜ν™˜ν•œλ‹€.
const dispatch = useDispatch();

✨ useStore

  • useStoreλ₯Ό μ΄μš©ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈ λ‚΄μ—μ„œ 직접 store에 μ ‘κ·Όν•  수 μžˆλ‹€.
const store = useStore();
store.dispatch({type: "ACTION"}):
store.getState();

❗ connect vs redux hooks

  • connectν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈμ™€ λ¦¬λ•μŠ€λ₯Ό μ—°λ™ν–ˆμ„ 경우 λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈκ°€ λ¦¬λ Œλ”λ§λ  λ•Œ ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈμ˜ propsκ°€ λ°”λ€Œμ§€ μ•Šμ•˜λ‹€λ©΄ λ¦¬λ Œλ”λ§λ˜μ§€ μ•ŠλŠ”λ‹€.
  • 반면, Hook을 μ‚¬μš©ν–ˆμ„ λ•ŒλŠ” μ΄λŸ¬ν•œ μ΅œμ ν™” μž‘μ—…μ΄ μžλ™μ μœΌλ‘œ 이루어지지 μ•ŠλŠ”λ‹€.
  • λ§Œμ•½ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈκ°€ λ¦¬λ Œλ”λ§λ  κ²½μš°κ°€ μžˆμ„ λ•ŒλŠ” React.memo()λ₯Ό μ‚¬μš©ν•˜μ—¬ μ΅œμ ν™” μž‘μ—…μ„ ν•΄μ€€λ‹€.

0개의 λŒ“κΈ€