[Today I Learned] 12월 2주차 day1

suwoncityboyyy·2022년 12월 12일
0

Redux (전역상태관리 라이브러리)

  • 라이브러리 설치
yarn add redux react-redux     // redux , react-redux 라이브러리 설치 
  • src 폴더안에 redux폴더를 만든 후 redux 폴더 안에 config폴더와 modules 폴더를 만든다.
  • config 폴더안에 configStore.js 파일을 만든 후, 아래 코드를 복붙한다.
    config폴더안에는 리덕스의 설정과 관련된 파일을 모아넣는다.

import { createStore } from "redux";
import { combineReducers } from "redux";

/*
1. createStore()
리덕스의 가장 핵심이 되는 스토어를 만드는 메소드(함수) 입니다. 
리덕스는 단일 스토어로 모든 상태 트리를 관리한다고 설명해 드렸죠? 
리덕스를 사용할 시 creatorStore를 호출할 일은 한 번밖에 없을 거예요.
*/

/*
2. combineReducers()
리덕스는 action —> dispatch —> reducer 순으로 동작한다고 말씀드렸죠? 
이때 애플리케이션이 복잡해지게 되면 reducer 부분을 여러 개로 나눠야 하는 경우가 발생합니다. 
combineReducers은 여러 개의 독립적인 reducer의 반환 값을 하나의 상태 객체로 만들어줍니다.
*/

const rootReducer = combineReducers({});
const store = createStore(rootReducer);

export default store;
  • module 폴더에는 state들이 모두 모여있을 파일을 생성한다.
    예를들어 todo의 모든 state를 관리하기 위해 파일을 만든 후 module 폴더에 넣는다.

  • index.js에 아래 코드를 복붙한다.

// 원래부터 있던 코드
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

// 우리가 추가할 코드
import store from "./redux/config/configStore";
import { Provider } from "react-redux";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(

        //App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.
  <Provider store={store}> 
    <App />
  </Provider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
  • 모듈파일 생성 후 ( ex) counter.js )
// 초기 상태값
const initialState = {
  number: 0,
};

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

// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
  • configStore.js 즉 store에 연결을 해야한다.
import { createStore } from "redux";
import { combineReducers } from "redux";
import counter from "../modules/counter";


const rootReducer = combineReducers({
  counter: counter,
});
const store = createStore(rootReducer);

export default store;
  • app.js파일에서 컴포넌트를 조회해본다. (useSelector)
import React from "react";
import { useSelector } from "react-redux"; 

const App = () => {
  const counterStore = useSelector((state) => state);
  const number = useSelector((state) => state.counter.number);
  console.log(counterStore);
  console.log(number);
  return <div></div>;
};

export default App;

Redux로 counter 만들어보기

//modules/counter.js


// 초기 상태값
const initialState = {
  number: 0,
};

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

// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
//App.js


import React from "react";
import { useSelector, useDispatch } from "react-redux"; // import 해주세요.

const App = () => {
  const dispatch = useDispatch();
  const number = useSelector((state) => state.counter.number);
  return (
    <div>
      {number}
      <button
        onClick={() => {
          dispatch({ type: "PLUS_ONE" });
        }}
      >
        +1
      </button>
      <button
        onClick={() => {
          dispatch({ type: "MINUS_ONE" });
        }}
      >
        -1
      </button>
    </div>
  );
};

export default App;

리팩토링 후 코드

//modules/counter.js


const PLUS_ONE = "PLUS_ONE";
const MINUS_ONE = "MINUS_ONE";

export const plusOne = () => {
  return {
    type: PLUS_ONE,
  };
};

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

const initialState = {
  number: 0,
};

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

// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
//App.js


import React from "react";
import { useSelector, useDispatch } from "react-redux"; // import 해주세요.
import { minusOne, plusOne } from "./redux/modules/counter";

const App = () => {
  const dispatch = useDispatch();
  const number = useSelector((state) => state.counter.number);
  return (
    <div>
      {number}
      <button
        onClick={() => {
          dispatch(plusOne());
        }}
      >
        +1
      </button>
      <button
        onClick={() => {
          dispatch(minusOne());
        }}
      >
        -1
      </button>
    </div>
  );
};

export default App;

payload까지 활용한 counter app

//modules/counter.js


//Action Value
const ADD_NUMBER = "ADD_NUMBER";
const DEL_NUMBER = "DEL_NUMBER";
//Action Creator
export const addNumber = (payload) => {
  return {
    type: ADD_NUMBER,
    payload,
  };
};
export const delNumber = (payload) => {
  return {
    type: DEL_NUMBER,
    payload,
  };
};

//Initial State
const InitialState = {
  number: 0,
};

//Reducer
const counter = (state = InitialState, action) => {
  switch (action.type) {
    case ADD_NUMBER: {
      return {
        number: state.number + action.payload,
      };
    }
    case DEL_NUMBER: {
      return {
        number: state.number - action.payload,
      };
    }
    default:
      return state;
  }
};

//export default reducer
export default counter;
//App.js


import React from "react";
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addNumber, delNumber } from "./redux/modules/counter";

const App = () => {
  const [number, setNumber] = useState(0);
  const globalNumber = useSelector((state) => state.counter.number);
  const dispatch = useDispatch();

  const onClickAddNumberHandler = () => {
    dispatch(addNumber(number));
  };

  const onClickDelNumberHandler = () => {
    dispatch(delNumber(number));
  };

  const onChangeHandler = (e) => {
    const { value } = e.target;
    setNumber(+value);
  };
  console.log(number);

  return (
    <div>
      {globalNumber}
      <input type="number" onChange={onChangeHandler} />
      <button onClick={onClickAddNumberHandler}>더하기</button>
      <button onClick={onClickDelNumberHandler}>빼기</button>
    </div>
  );
};

export default App;
profile
주니어 개발자 기술노트

0개의 댓글