본문 바로가기

JavaScript/React

Redux

728x90

Redux

'

중앙 데이터 관리소(Store)로 상태관리소로 접근 & 제어

공용 변수 저장소

전역 상태관리 라이브러리 즉, Global State를 의미하고 그것을 관리하게 도와주는 라이브러리(패키지)

 

필요 이유

Props로 State를 공유하는 방법에는 불편한 점 개선


세팅

$ yarn add redux react-redux

리덕스 카운터 프로그램 세팅

 

modules/counter.js

// 초기 상태값(state)
const initialState = {
    number: 0,
}

// const [number, setNumber] = useState(0)

// 리듀서 : 'state에 변화를 일으키는' 함수
// (1) state를 action의 type에 따라 변경하는 함수

// input : state와 action
const counter = (state = initialState, action) => {
    switch (action.type) {
        default:
            return state;
    }
}

export default counter;

 

config/configStore.js

// 중앙 데이터 관리소(store)를 설정하는 부분
import { createStore } from "redux";
import { combineReducers } from "redux";
import counter from "../modules/counter";
import users from "../modules/users";

const rootReducer = combineReducers({
    // 리듀서들!!!
    counter: counter,
    users,
});
const store = createStore(rootReducer);

export default store;

 

App.jsx

import { useSelector } from 'react-redux';
import './App.css';

function App() {

  // 여기에서 store에 접근하여 counter의 값을 읽어오고 싶다.
  // useSelector
  const data = useSelector((state) => {
    return state;
  });

  console.log(data);

  return (
    <div>Redux!</div>
  );
}

export default App;


Redux 흐름

1. dispatch가 action(객체(key-value), type, payload)을 store에 던진다.

2. store는 action객체에 있는 type에 따라 state를 변경

 


리덕스 카운터 프로그램 실습

 

modules/counter.js

// 초기 상태값(state)
const initialState = {
    number: 0,
}

// const [number, setNumber] = useState(0)

// 리듀서 : 'state에 변화를 일으키는' 함수
// (1) state를 action의 type에 따라 변경하는 함수

// input : state와 action
const counter = (state = initialState, action) => {
    console.log(state);
    switch (action.type) {
        case "PLUS_ONE":
            return {
                number: state.number + 1,
            };
        case 'MINUS_ONE':
            return {
                number: state.number - 1,
            };
        default:
            return state;
    }
}

export default counter;

 

App.jsx

import { useDispatch, useSelector } from 'react-redux';
import './App.css';
import counter from './redux/modules/counter';

function App() {

  // 여기에서 store에 접근하여 counter의 값을 읽어오고 싶다.
  // useSelector
  const data = useSelector((state) => {
    return state.counter.number;
  });

  // dispatch를 가져와보자.
  const dispatch = useDispatch();

  console.log(data);

  return (
    <>
      <div> 현재 카운트 : {data}</div>
      <button onClick={() => {
        // +1을 해주는 로직을 써주면 된다.
        dispatch({
          type: 'PLUS_ONE',
        });
      }}>+</button>
      <button onClick={() => {
        // -1을 해주는 로직을 써주자.
        dispatch({
          type: 'MINUS_ONE',
        });
      }}>-</button>
    </>
  );
}

export default App;


Redux Action Value

 

휴먼 에러 발생 가능성이 많은 하드코딩 방식을 변수화

 

modules/counter.js

// action value
export const PLUS_ONE = "PLUS_ONE";
export const MINUS_ONE = "MINUS_ONE"

// 초기 상태값(state)
const initialState = {
    number: 0,
}

// input : state와 action
const counter = (state = initialState, action) => {
    console.log(state);
    switch (action.type) {
        case PLUS_ONE:
            return {
                number: state.number + 1,
            };
        case MINUS_ONE:
            return {
                number: state.number - 1,
            };
        default:
            return state;
    }
}

export default counter;

 

App.jsx

import { PLUS_ONE, MINUS_ONE } from './redux/modules/counter';

...

function App() {

	...

  return (
    <>
      <div> 현재 카운트 : {data}</div>
      <button onClick={() => {
        // +1을 해주는 로직을 써주면 된다.
        dispatch({
          type: PLUS_ONE,
        });
      }}>+</button>
      <button onClick={() => {
        // -1을 해주는 로직을 써주자.
        dispatch({
          type: MINUS_ONE,
        });
      }}>-</button>
    </>
  );
}

export default App;

Redux Action Creator

 

modules/counter.js

// action value
const PLUS_ONE = "counter/PLUS_ONE";
const MINUS_ONE = "conter/MINUS_ONE"

// action creator : action value를 return 하는 함수
export const plusOne = () => {
    return {
        type: PLUS_ONE,
    }
}

export const minusOne = () => {
    return {
        type: MINUS_ONE,
    }
}

 

App.jsx

import { PLUS_ONE, MINUS_ONE } from './redux/modules/counter';
import { plusOne, minusOne } from './redux/modules/counter';

function App() {

	...

  return (
    <>
      <div> 현재 카운트 : {data}</div>
      <button onClick={() => {
        // +1을 해주는 로직을 써주면 된다.
        dispatch(plusOne());
      }}>+</button>
      <button onClick={() => {
        // -1을 해주는 로직을 써주자.
        dispatch(minusOne());
      }}>-</button>
    </>
  );
}

Redux Payload

탑재 화물.

전달되는 어떠한 실체!

 

App.jsx

import { useDispatch, useSelector } from 'react-redux';
import './App.css';
import counter from './redux/modules/counter';
import { PLUS_ONE, MINUS_ONE } from './redux/modules/counter';
import { plusOne, minusOne } from './redux/modules/counter';
import { useEffect, useState } from 'react';
import { plusN, minusN } from './redux/modules/counter';

function App() {
  const [number, setNumber] = useState(0);

  // 여기에서 store에 접근하여 counter의 값을 읽어오고 싶다.
  // useSelector
  const data = useSelector((state) => {
    return state.counter.number;
  });

  // useEffect(() => {
  //   console.log("number->" + number);
  // }, [number]);


  // dispatch를 가져와보자.
  const dispatch = useDispatch();

  return (
    <>
      <div> 현재 카운트 : {data}</div>
      <div>
        <input type='number' 
          value={number}
          onChange={(event) => {
            const { value } = event.target;
            setNumber(+value);
          }}  
        />
      </div>
      <button onClick={() => {
        // +1을 해주는 로직을 써주면 된다.
        dispatch(plusN(number));
        setNumber(0);
      }}>+</button>
      <button onClick={() => {
        // -1을 해주는 로직을 써주자.
        dispatch(minusN(number));
        setNumber(0);
      }}>-</button>
    </>
  );
}

export default App;

 

modules/counter.js

// action value
const PLUS_ONE = "counter/PLUS_ONE";
const MINUS_ONE = "conter/MINUS_ONE";
const PLUS_N = "counter/PLUS_N";
const MINUS_N = "conter/MINUS_N"

// action creator : action value를 return 하는 함수
export const plusOne = () => {
    return {
        type: PLUS_ONE,
    }
}

export const minusOne = () => {
    return {
        type: MINUS_ONE,
    }
}

export const plusN = (payload) => {
    return {
        type: PLUS_N,
        payload: payload,
    }
}

export const minusN = (payload) => {
    return {
        type: MINUS_N,
        payload,
    }
}

// 초기 상태값(state)
const initialState = {
    number: 0,
}

// const [number, setNumber] = useState(0)

// 리듀서 : 'state에 변화를 일으키는' 함수
// (1) state를 action의 type에 따라 변경하는 함수

// input : state와 action
// action 객체라는 것은 action type을 payload 만큼 처리하는 것이다!
// ex : payload가 3이다 3만큼 증가.
const counter = (state = initialState, action) => {
    console.log(state);
    switch (action.type) {
        case PLUS_ONE:
            return {
                number: state.number + 1,
            };
        case MINUS_ONE:
            return {
                number: state.number - 1,
            };
        case PLUS_N:
            return {
                number: state.number + action.payload,
            }
        case MINUS_N:
            return {
                number: state.number - action.payload,
            }
        default:
            return state;
    }
}

export default counter;

 

 

'JavaScript > React' 카테고리의 다른 글

Hooks - useEffect, 의존성 배열(dependency array)  (0) 2023.06.07
Hooks - useState  (0) 2023.06.07
숙련주차, GlobalStyles, Sass  (0) 2023.06.07
숙련주차, Styled Components ,Css-in-JS  (0) 2023.06.07
반복되는 Component 처리하기  (0) 2023.06.07