๐Ÿ’ป Web

[React] redux ์ •๋ฆฌ

ji_wonna 2022. 8. 11. 23:28

redux๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฆฌ์•กํŠธ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค.

useState๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ๊ฒฝ์šฐ ๋ฃจํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ข…์† ์ปดํฌ๋„ŒํŠธ๋กœ props๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๋ฐฉ์‹์€ ์ปดํฌ๋„ŒํŠธ์˜ ๊ตฌ์กฐ๊ฐ€ ๊ฐ„๋‹จํ•˜๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

ํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๊ฑฐ๋‚˜ ๋ณต์žกํ•ด์ ธ์„œ ๊ทธ ํ•˜์œ„์˜ ํ•˜์œ„์˜ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ state๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด, props๋ฅผ ๊ณ„์† ๋‚ด๋ ค์ค˜์•ผ ํ•˜๊ณ  ์ „๋‹ฌ๋ฐ›์€ props๊ฐ€ ์–ด๋Š ์ปดํฌ๋„ŒํŠธ์—์„œ ์˜จ ๊ฒƒ์ธ์ง€ ์•Œ๊ธฐ ํž˜๋“ค์–ด์ง„๋‹ค. ์‹ฌ์ง€์–ด ํ•ด๋‹น state๊ฐ€ ํ•„์š” ์—†๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌํ•ด์ฃผ๊ธฐ ์œ„ํ•ด props๋ฅผ ๋ฐ›๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ข…์†์„ฑ์„ ํƒˆํ”ผํ•˜๊ธฐ ์œ„ํ•ด ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ๋ ˆ๋ฒจ์—์„œ state๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ๊ฒƒ์ด ๋ฆฌ๋•์Šค์ด๋‹ค.

store์— state๋ฅผ ์ €์žฅํ•˜๊ณ  ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ state์™€ state๋ฅผ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ๋ฐ›๋Š”๋‹ค.

๋ฆฌ๋•์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „, ์•Œ์•„์•ผ ํ•  ๊ฐœ๋…์ด ๋ช‡ ๊ฐ€์ง€ ๋“ฑ์žฅํ•œ๋‹ค.

 

์•ก์…˜

์ƒํƒœ์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธธ ๋•Œ ๋ฐœ์ƒํ•˜๋ฉฐ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ํ‘œํ˜„๋œ๋‹ค.

์•ก์…˜ ๊ฐ์ฒด๋Š” ์—ฌ๋Ÿฌ ์†์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , ๊ฐ๊ฐ์˜ ์•ก์…˜์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ type ์†์„ฑ์€ ๋ฐ˜๋“œ์‹œ ๊ฐ–๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

๋‚˜๋จธ์ง€ ์†์„ฑ๋“ค์€ ์ž‘์„ฑ์ž๊ฐ€ ํ•„์š”ํ•œ ์ƒํƒœ๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

//modules/survey.js
//์•ก์…˜ ํƒ€์ž… ์ •์˜
const SURVEY_INIT = 'survey/INIT';
const SURVEY_INSERT = 'survey/INSERT';
//์•ก์…˜ ์ƒ์„ฑ ํ•จ์ˆ˜
export const surveyInit = () => ({
  type: SURVEY_INIT,
});
export const surveyInsert = (surveyResult) => ({
  type: SURVEY_INSERT,
  surveyResult,
});

 

๋ฆฌ๋“€์„œ

๋ฆฌ๋“€์„œ๋Š” ์•ก์…˜์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์ผ์œผ์ผœ์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์•ก์…˜ ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์™€์„œ ํ•ด๋‹น ์•ก์…˜์— ๋งž๋Š” ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ƒˆ๋กœ์šด ์ƒํƒœ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

๋ฆฌ๋“€์„œ๋Š” ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŒ์•ฝ ๋ฆฌ๋“€์„œ ํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด, ์ด๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ฃผ๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค. (๋ฃจํŠธ ๋ฆฌ๋“€์„œ)

//modules/survey.js
//์ดˆ๊ธฐ์ƒํƒœ
const initialState = {
  surveyResult: [],
};
//reducer ํ•จ์ˆ˜
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case SURVEY_INIT:
      return {
        ...state,
        surveyResult: [],
      };
    case SURVEY_INSERT:
      return {
        ...state,
        surveyResult: state.surveyResult.concat(action.surveyResult),
      };
    default:
      return state;
  }
};
//modules/index.js
import { combineReducers } from 'redux';
import survey from './survey';

const rootReducer = combineReducers({
  survey,//์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฆฌ๋“€์„œ๋ผ๋ฉด ์ด์–ด์„œ ์ž‘์„ฑํ•ด์ค€๋‹ค.
});

export default rootReducer;

 

์Šคํ† ์–ด

๋ฆฌ์•กํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ฆฌ๋•์Šค๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•˜๋Š” ์ƒํƒœ ์ €์žฅ์†Œ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค. ์Šคํ† ์–ด๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์— ํ•˜๋‚˜๋งŒ ์กด์žฌํ•œ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ๋ฃจํŠธ ๋ ˆ๋ฒจ์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ† ์–ด๋Š” index.js ํŒŒ์ผ์—์„œ ๋งŒ๋“ค์–ด์ค˜์•ผํ•œ๋‹ค. ์›๋ž˜๋Š” ๋ฆฌ๋•์Šค์—์„œ ์ œ๊ณตํ•˜๋Š” createStore๋กœ ์Šคํ† ์–ด๋ฅผ ๋งŒ๋“ค์–ด์คฌ์ง€๋งŒ ์ด์ œ๋Š” ์‚ญ์ œ๋๊ธฐ ๋•Œ๋ฌธ์— @reduxjs/toolkit์˜ configureStore๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก <App>์ปดํฌ๋„ŒํŠธ๋ฅผ react-redux์—์„œ ์ œ๊ณตํ•˜๋Š” <Provider>๋กœ ๋ฌถ์–ด์ค˜์•ผ ํ•œ๋‹ค.

//src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import rootReducer from './modules';

const store = configureStore({
  reducer: rootReducer,
});

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

 

์ด์ œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ฐ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค๐Ÿ˜†

connect ํ•จ์ˆ˜๋กœ ๋ฆฌ๋•์Šค๋ฅผ ์—ฐ๋™ํ•ด์„œ ์จ๋„ ๋˜์ง€๋งŒ ๋‚˜๋Š” react-redux์—์„œ ์ œ๊ณตํ•˜๋Š” Hook์„ ์ด์šฉํ–ˆ๋‹ค.

์ƒํƒœ ์กฐํšŒ๋Š” useSelector(), ์•ก์…˜ ๋””์ŠคํŒจ์น˜๋Š” useDispatch()๋ฅผ ์‚ฌ์šฉํ–ˆ์œผ๋ฉฐ connect ํ•จ์ˆ˜์— ๋น„ํ•ด ์ฝ”๋“œ์˜ ๊ธธ์ด๊ฐ€ ์งง์•„์ง€๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง„๋‹ค๋Š” ์žฅ์ ์„ ๊ฐ–๋Š”๋‹ค.

 

useSelector() : ์ƒํƒœ ์กฐํšŒ

๋ฆฌ์•กํŠธ์—์„œ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ๋•Œ window.location.href="/"์™€ ๊ฐ™์ด ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด๋™ํ•˜๊ฒŒ ๋˜๋ฉด state๊ฐ€ ์ดˆ๊ธฐํ™”๋ผ์„œ ์ƒํƒœ ์กฐํšŒ๋ฅผ ํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋ฆฌ์•กํŠธ ํ›…์ธ useNavigate()๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

useDispatch() : ์•ก์…˜ ๋””์ŠคํŒจ์น˜

์Šคํ† ์–ด์˜ ๋‚ด์žฅ ํ•จ์ˆ˜์ธ dispatch๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ›…์ด๋‹ค. ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ๋Š” ์•ก์…˜ ๊ฐ์ฒด๋‚˜ ์•ก์…˜ ์ƒ์„ฑ ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

import { useSelector, useDispatch } from 'react-redux';
const survey = useSelector((state) => state.survey.surveyResult);
const dispatch = useDispatch();
dispatch(surveyInsert(answer));