본문 바로가기

Redux로 간단한 Count 기능 구현하기

Redux로 간단한 Count 기능 구현하기

 

Redux를 사용하기 위해서는 redux와 react-redux를 설치해야한다.

설치를 하고 나면,

 

DEPENDENCIES

  redux, react-redux가 설치되어 있는 것을 확인할 수 있다.

 .
 .
 .
 "dependencies": {
    "@types/react": "^16.8 || ^17.0 || ^18.0",
    "@types/react-dom": "^16.8 || ^17.0 || ^18.0",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "react-native": ">=0.59",
    "react-redux": "^8.0.2",
    "redux": "^4"
  },
  .
  .
  .




index.js

import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

// (1) react-redux에서 Provider을 불러온다. (Provider은 store을 쉽게 사용할 수 있게 하는 컴포넌트)
// 해당 컴포넌트를 불러온 다음, Store을 사용할 컴포넌트를 감싼 후, Provider 컴포넌트의 props로 store을 설정해준다.
import { Provider } from 'react-redux';

// (2) redux에서 createStore을 불러온다.
import { legacy_createStore as createStore } from 'redux';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

// (6) Action은 어떻게 state를 변경할지 정의해놓은 객체로 type은 필수로 지정을 해줘야 한다
export const increase = () => {
  return {
    type: 'INCREASE',
  };
};

export const decrease = () => {
  return {
    type: 'DECREASE',
  };
};

const count = 1;

// (5) Reducer를 생성할 때에는 초기 상태(default value)를 첫 번째 인자, action 객체가 두 번째 인자로 들어온다.
//     action 객체에서 정의한 type에 따라 새로운 state를 리턴하며, 새로운 상태는 전역 변수 저장소 store에 저장된다.
const counterReducer = (state = count, action) => {
  // Action 객체의 type 값에 따라 분기하는 switch 조건문 
  switch (action.type) {
    case 'INCREASE':             //action === 'INCREASE'일 경우
      return state + 1;

    case 'DECREASE':             // action === 'DECREASE'일 경우
      return state - 1;

    case 'SET_NUMBER':          // action === 'SET_NUMBER'일 경우
      return action.payload;

    default:                    // 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴
      return state;
  }
};

// (4) 변수 store에 createStore 메서드를 통해 store을 만든 후, createStore에 인자로 Reducer 함수를 전달한다.
const store = createStore(counterReducer);


// (3) 전역 상태 저장소 store을 사용하기 위해서는 App 컴포넌트를 Provider로 감싸준 후, props로 변수 store을 전달해준다.
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

 


App.js

import React from 'react';
import './style.css';

// (1) react-redux에서 useDispatch를 불러온다.
import { useDispatch, useSelector } from 'react-redux';

// (2) Action Creater 함수 increase, decrease를 불러온다.
import { increase, decrease } from './index.js';

export default function App() {
// (3) useDispatch의 실행 값을 변수에 저장해서 dispatch 함수를 사용한다.
  const dispatch = useDispatch();
  console.log(dispatch) // f dispatch() 가 뜬다.
  const state = useSelector((state) => state);

// (4) 이벤트 핸들러 안에서 dispatch를 통해 action 객체를 Reducer 함수로 전달한다.
  const plusNum = () => {
    dispatch(increase());
  };

  const minusNum = () => {
    dispatch(decrease());
  };

  return (
    <div className="container">
      <h1>{`Count: ${state}`}</h1>
      <div>
        <button className="plusBtn" onClick={plusNum}>
          +
        </button>
        <button className="minusBtn" onClick={minusNum}>
          -
        </button>
      </div>
    </div>
  );
}

 

폴더 나누기


한 파일에 다양한 기능의 코드들을 작성하는 것은 바람직하지 않다.

앞서 구현한 Redux의 코드를 역할 별로 리팩토링 한 결과는 아래와 같다.

 

 

 

다른 예시
// *** Redux의 기본 구현 방식 

//App.js에 수량을 +1, -1 하는 버튼이 각각 있다.

//App.js
import React from 'react';
import styled from 'styled-components';
import { useSelector, useDispatch } from 'react-redux';

export default function App() {
  const number = useSelector((state) => state);
  console.log(number); // 0
  const dispatch = useDispatch();

  const plusNum = () => {
    dispatch({ type: 'Plus' });
  };

  const minusNum = () => {
    dispatch({ type: 'Minus' });
  };

  return (
    <Container>
      <Text>{`수량 : ${number}`}</Text>
      <Button onClick={plusNum}>👍</Button>
      <Button onClick={minusNum}>👎</Button>
    </Container>
  );
}

//reducer.js
export const reducer = (initialState = 0, action) => {
  let newState = initialState;
  switch (action.type) {
    case 'Plus':
      return newState + 1;
    case 'Minus':
      return newState - 1;
    default:
      return initialState;
  }
};
  • newState 변수는 현재 상태값(initialState)을 복사하여 변경 가능한 변수를 만들기 위해 사용된다.
    • 이렇게 함으로써, 원래의 상태값을 변경하지 않고도 새로운 값을 할당할 수 있다.
    • Reducer는 순수 함수(pure function)로 작성되어야 한다. 따라서, reducer 함수 내에서 상태값을 직접 변경하는 것은 권장되지 않는다.
    • 상태값을 변경하는 대신, 이전 상태값을 복사한 새로운 상태값을 만들고, 이를 새로운 상태값으로 반환하는 것이 좋다.

 

728x90
⬆︎