ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] Redux
    codeStates front-end/React 2023. 2. 24. 18:20
    반응형

    목차

       

       

      📌  Redux

       

       

       

      📍Redux 개요

       

      보통 리액트에서 최상위 컴포넌트 -> 부모 컴포넌트 -> 자식 컴포넌트가 일반적이지만,

      다소 비효율적이라고 느낄 수 있다.

       

      1. 해당 상태를 직접 사용하지 않는 최상위 컴포넌트, 컴포넌트1, 컴포넌트2도 상태 데이터를 가짐

      2. 상태 끌어올리기, Props 내려주기를 여러 번 거쳐야 함

      3. 애플리케이션이 복잡해질수록 데이터 흐름도 복잡해짐

      4. 컴포넌트 구조가 바뀐다면, 지금의 데이터 흐름을 완전히 바꿔야 할 수도 있음

       

      허나 Redux는 전역 상태를 관리할 수 있는 저장소인 Store를 제공함으로써 이 문제들을 해결

       

       

       

       

       

       

      📍Redux 구조

       

       

      🔗 Redux 상태 관리

       

      Action → Dispatch → Reducer → Store 순서

       

      1. 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성
      2. 이 Action 객체는 Dispatch 함수의 인자로 전달
      3. Dispatch 함수는 Action 객체를 Reducer 함수로 전달
      4. Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경
      5. 상태가 변경되면, React는 화면을 다시 렌더링 

       

      🔗 Redux  설치

       

      npm install redux react-redux

       

      🔗 Store

       

      상태 관리되는 오직 하나뿐인 저장소의 역할

       

      // createStore 메서드를 활용해 Reducer를 연결 -> Store 생성
      import { createStore } from 'redux';
      
      const store = createStore(rootReducer);

       

      Store 실습

       

      // App.js
      
      import React from 'react';
      import './style.css';
      
      export default function App() {
        return (
          <div>
            <h1>{`Count: ${1}`}</h1>
          </div>
        );
      }
      
      // index.js
      import React from 'react';
      import { createRoot } from 'react-dom/client';
      import App from './App';
      import { Provider } from 'react-redux';
      import { legacy_createStore as createStore } from 'redux';
      
      const rootElement = document.getElementById('root');
      const root = createRoot(rootElement);
      
      const reducer = () => {};
      
      const store = createStore(reducer);
      
      root.render(
       <Provider store={store}>
        <App />
       </Provider>
      );

       

      🔗 Reducer

      Reducer는 Dispatch에게서 전달받은 Action 객체의 type 값에 따라서 상태를 변경시키는 함수

      Reducer는 순수함수여야 한다

       

       

       

      Reducer 실습

       

      import React from 'react';
      import { createRoot } from 'react-dom/client';
      import App from './App';
      import { Provider } from 'react-redux';
      import { legacy_createStore as createStore } from 'redux';
      
      const rootElement = document.getElementById('root');
      const root = createRoot(rootElement);
      
      const count = 1;
      
      // Reducer를 생성할 때에는 초기 상태를 인자로 요구합니다.
      const counterReducer = (state = count, action) => {
        // Action 객체의 type 값에 따라 분기하는 switch 조건문입니다.
        switch (action.type) {
          //action === 'INCREASE'일 경우
          case 'INCREASE':
            return state + 1;
      
          // action === 'DECREASE'일 경우
          case 'DECREASE':
            return state - 1;
      
          // action === 'SET_NUMBER'일 경우
          case 'SET_NUMBER':
            return action.payload;
      
          // 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴
          default:
            return state;
        }
      };
      
      const store = createStore(counterReducer);
      
      root.render(
        <Provider store={store}>
          <App />
        </Provider>
      );

       

      💡여러 개의 Reducer를 사용하는 경우

       

      // combineReducers 메서드를 사용해서 하나의 Reducer로 합쳐준다
      import { combineReducers } from 'redux';
      
      const rootReducer = combineReducers({
        counterReducer,
        anyReducer,
        ...
      });

       

      🔗 Action

       

      Action은 말 그대로 어떤 액션을 취할 것인지를 정의해놓은 객체

      Action객체를 생성하는 함수를 만들어 사용하는 경우가 많다

       

      type -> 필수로 지정(대문자와 Snake Case), 필요에 따라 payload를 작성해 구체적인 값을 전달

       

      // Action객체 직접 작성
      
      // payload가 필요 없는 경우
      { type: 'INCREASE' }
      
      // payload가 필요한 경우
      { type: 'SET_NUMBER', payload: 5 }
      
      // Action 생성자
      
      // payload가 필요 없는 경우
      const increase = () => {
        return {
          type: 'INCREASE'
        }
      }
      
      // payload가 필요한 경우
      const setNumber = (num) => {
        return {
          type: 'SET_NUMBER',
          payload: num
        }
      }

       

      Action  실습

       

      import React from 'react';
      import { createRoot } from 'react-dom/client';
      import App from './App';
      import { Provider } from 'react-redux';
      import { legacy_createStore as createStore } from 'redux';
      
      const rootElement = document.getElementById('root');
      const root = createRoot(rootElement);
      
      export const increase = () => {
        return {
          type: 'INCREASE'
        }
      }
      
      export const decrease = () => {
        return {
          type: 'DECREASE'
        }
      }
      
      
      
      const count = 1;
      
      // Reducer를 생성할 때에는 초기 상태를 인자로 요구합니다.
      const counterReducer = (state = count, action) => {
        // Action 객체의 type 값에 따라 분기하는 switch 조건문입니다.
        switch (action.type) {
          //action === 'INCREASE'일 경우
          case 'INCREASE':
            return state + 1;
      
          // action === 'DECREASE'일 경우
          case 'DECREASE':
            return state - 1;
      
          // action === 'SET_NUMBER'일 경우
          case 'SET_NUMBER':
            return action.payload;
      
          // 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴
          default:
            return state;
        }
        // Reducer가 리턴하는 값이 새로운 상태가 됩니다.
      };
      
      const store = createStore(counterReducer);
      
      root.render(
        <Provider store={store}>
          <App />
        </Provider>
      );

       

      🔗 Dispatch

       

      Dispatch는 Reducer로 Action을 전달해주는 함수

      Dispatch의 전달인자로 Action 객체가 전달

       

      // Action 객체를 직접 작성하는 경우
      dispatch( { type: 'INCREASE' } );
      dispatch( { type: 'SET_NUMBER', payload: 5 } );
      
      // 액션 생성자(Action Creator)를 사용하는 경우
      dispatch( increase() );
      dispatch( setNumber(5) );

       

      🔗 Redux Hooks

       

      Redux Hooks는 React-Redux에서 Redux를 사용할 때 활용할 수 있는 Hooks 메서드를 제공

      useSelector(), useDispatch()

       

      useDispatch()

       

      Action 객체를 Reducer로 전달해 주는 Dispatch 함수를 반환하는 메서드

       

      import { useDispatch } from 'react-redux'
      
      const dispatch = useDispatch()
      dispatch( increase() )
      console.log(counter) // 2
      
      dispatch( setNumber(5) )
      console.log(counter) // 5

       

      useSelector()

       

      컴포넌트와 state를 연결하여 Redux의 state에 접근할 수 있게 해주는 메서드

       

      // Redux Hooks 메서드는 'redux'가 아니라 'react-redux'에서 불러옵니다.
      import { useSelector } from 'react-redux'
      const counter = useSelector(state => state)
      console.log(counter) // 1

       

       

      useDispatch(), useSelector() 실습 - Redux 예제

       

      import React from 'react';
      import './style.css';
      // react-redux에서 useDispatch, useSelector 사용
      import { useDispatch, useSelector } from 'react-redux';
      // index.js에서 action객체 함수 사용
      import { increase, decrease } from './index.js';
      
      export default function App() {
        // Reducer로 전달해 주는 Dispatch 함수를 반환하는 메소드
        const dispatch = useDispatch();
        // useSelector() 사용하여 redux가 state에 접근할수 있게 한다
        const state = useSelector((state) => state);
        console.log(state);
      
        const plusNum = () => {
        // 이벤트 함수에 dispatch 함수를 사용하여 값을 저장
          dispatch(increase());
        };
      
        const minusNum = () => {
        // 이벤트 함수에 dispatch 함수를 사용하여 값을 저장
          dispatch(decrease());
        };
      
        return (
          <div className="container">
            {/* 화면에 렌더링 하기 위해 state값을 템플릿리터럴에 넣어준다 */}
            <h1>{`Count: ${state}`}</h1>
            <div>
              <button className="plusBtn" onClick={plusNum}>
                +
              </button>
              <button className="minusBtn" onClick={minusNum}>
                -
              </button>
            </div>
          </div>
        );
      }

       

       

       

      Redux의 세 가지 원칙

      Redux에는 세 가지 원칙이 있습니다. 각각의 원칙이 Redux의 어떤 구성 요소와 연결이 되는지 확인하세요.

      1. Single source of truth

      동일한 데이터는 항상 같은 곳에서 가지고 와야 한다는 의미입니다. 즉, Redux에는 데이터를 저장하는 Store라는 단 하나뿐인 공간이 있음과 연결이 되는 원칙입니다.

      2. State is read-only

      상태는 읽기 전용이라는 뜻으로, React에서 상태갱신함수로만 상태를 변경할 수 있었던 것처럼, Redux의 상태도 직접 변경할 수 없음을 의미합니다. 즉, Action 객체가 있어야만 상태를 변경할 수 있음과 연결되는 원칙입니다.

      3. Changes are made with pure functions

      변경은 순수함수로만 가능하다는 뜻으로, 상태가 엉뚱한 값으로 변경되는 일이 없도록 순수함수로 작성되어야하는 Reducer와 연결되는 원칙입니다.

      반응형

      'codeStates front-end > React' 카테고리의 다른 글

      [React] 번들링과 웹팩  (0) 2023.03.20
      [React]Cmarket Redux  (0) 2023.02.27
      [React] Storybook, useRef  (0) 2023.02.20
      [React] custom component/ Styled-Component  (0) 2023.02.20
      [React] UX 디자인  (0) 2023.02.15

      댓글

    Designed by Tistory.