리덕스_2

nevermind·2022년 8월 2일
0
post-custom-banner

리덕스의 흐름잡기


1. View 에서 액션이 일어난다.
2. dispatch 에서 action이 일어나게 된다.
3. action에 의한 reducer 함수가 실행되기 전에 middleware가 작동한다.
4. middleware 에서 명령내린 일을 수행하고 난뒤, reducer 함수를 실행한다.
5. reducer 의 실행결과 store에 새로운 값을 저장한다.
6. store의 state에 subscribe 하고 있던 UI에 변경된 값을 준다.
출처 : https://velog.io/@annahyr/리덕스-흐름-이해하기

  • 스토어에는 state들을 저장해준다(props로 받고 싶은 것들을 전역으로 쓸 수 있도록)

  • 스토어는 createStore, combineReducers(보내줄 모듈)를 사용하여 합쳐준다

  • 모듈에는 액션생성함수, reducer 이 있음

  • 스토어에 있는 것을 액션함수로 요청함(ex. ADD_TODO)

  • ADD_TODO로 받은 것을 reducer(보내줄 모듈의 함수)가 처리(더해주는 행위)

  • 컴포넌트에서 인자를 넘겨 액션생성함수를 쓰고 싶다면 dispatch를 이용하여 이용하고 싶은 함수에 인자를 넘겨서 사용 가능
    ex)

let data = {
      title: title,
      body: body,
    }
    dispatch(addTodo(data))

1. 리덕스 설정

yarn add redux react-redux설치 (react, react-redux 설치

폴더구조를 생성
- redux 폴더에는 리덕스와 관련된 코드들 모두 모아둠
- config 폴더는 리덕스 설정과 관련된 파일들을 놓을 폴더
- configStore "중앙 state 관리소"인 Store를 만드는 설정 코드들이 있는 파일
- modules 우리가 만들 State들의 그룹 (ex, 투두리스트에 필요한 state들이 모두 있는 곳

  • src/configStore.js (중앙 관리소 :Store)

    import { createStore } from "redux";
    import { combineReducers } from "redux";
    
    const rootReducer = combineReducers({});
    const store = createStore(rootReducer);
    
    export default store;
  • 디렉토리 최상단 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();
    

2. 모듈 만들기

모듈: State의 그룹

  • src/modules/counter.js
    // 초기 상태값
    const initialState = {
     number: 0,
    };
    // 리듀서
    const counter = (state = initialState, action) => {
     switch (action.type) {
       default:
         return state;
     }
    };
    // 모듈파일에서는 리듀서를 export default 한다.
    export default counter;
    - 구성을 살펴보자
    1) initialState === 초기 상태값 (객체, 배열, 원시데이터 등 가능)
    2) Reducer === 변화를 일으키는 함수 (setState같은 역할,
    그리고 리듀서의 인자에 보면 (state = intialState, action) state와 action을 꺼내서 사용할 수 있음

3. 모듈을 스토어에 연결시키기

// src/redux/modules/config/configStore.js

    // 원래 있던 코드
    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;
스토어와 모듈을 연결시킴

4. 스토어와 모듈 연결 확인하기

  • useSelector = 스토어 조회(react-redux에서 제공하는 훅)
  • 우리가 생성한 모듈을 스토어에 잘 연결했는지 확인하는 방법은 컴포넌트에서 스토어를 직접 조회
  • useSelcetor 방법
// 1. store에서 꺼낸 값을 할당 할 변수를 선언합니다.
const number = 

// 2. useSelector()를 변수에 할당해줍니다.
const number = useSelector() 

// 3. useSelector의 인자에 화살표 함수를 넣어줍니다.
const number = useSelector( ()=>{} )

// 4. 화살표 함수의 인자에서 값을 꺼내 return 합니다. 
// 우리가 useSelector를 처음 사용해보는 것이니, state가 어떤 것인지 콘솔로 확인해볼까요?
const number = useSelector((state) => {
	console.log(state)
	return state
});


number을 사용하고 싶다면
const number = useSelector(state => state.counter.number); // 0

5. 액션 creator 생성

  • 액션객체: { type : "PLUS_ONE" };
  • dispatch를 이용하여 “명령”(액션 객체) 보내기
// src/App.js

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

const App = () => {
  const dispatch = useDispatch(); // dispatch 생성
  return (
    <div>
      <button
				// 이벤트 핸들러 추가
        onClick={() => {
					// 마우스를 클릭했을 때 dispatch가 실행되고, ()안에 있는 액션객체가 리듀서로 전달된다.
          dispatch({ type: "PLUS_ONE" }); 
        }}
      >
				+ 1
      </button>
    </div>
  );
};

export default App;
  • 리듀서에서는 이렇게 받는다
// 리듀서
const counter = (state = initialState, action) => {
  console.log(action);
  switch (action.type) {
		// PLUS_ONE이라는 case를 추가한다.
		// 여기서 말하는 case란, action.type을 의미한다.
		// dispatch로부터 전달받은 action의 type이 "PLUS_ONE" 일 때
		// 아래 return 절이 실행된다. 
    case "PLUS_ONE":
      return {
				// 기존 state에 있던 number에 +1을 더한다.
        number: state.number + 1,
      };

    default:
      return state;
  }
};

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

action이 {type: “PLUS_ONE”} 이기 때문에, 리듀서 안에 있는 스위치문은 action.type을 조회.
그리고 그것이 일치하면 return 절이 실행되고 새로운 state를 반환.
코드로 보면 스위치문에 case를 하나 추가해주는 것으로 완료

  • 액션객체란, 반드시 type이란 key를 가져야 하는 객체
  • 리듀서로 보낼 “명령"
  • 리듀서란, 디스패치를 통해 전달받은 액션객체를 검사하고, 조건이 일치했을 때 새로운 상태값을 만들어내는 “변화를 만들어내는" 함수
  • 디스패치(dispatch)를 사용하기위해서는 useDispatch() 라는 훅을 이용
  • 액션객체 type의 value는 대문자로 작성한다. (JS에서 상수는 대문자로 작성하는 룰이 있음)

- 액션 creator

  • 액션객체를 한 곳에서 관리할 수 있도록 “함수"와 액션 value를 상수로 만드는 것
const PLUS_ONE = "PLUS_ONE"; // value는 상수로 생성

// 액션객체를 반환하는 함수 생성
// export 가 붙는 이유는 plusOne()는 밖으로 나가서 사용될 예정이기 때문입니다.
export const plusOne = () => { 
  return {
    type: PLUS_ONE, // type에는 위에서 만든 상수로 사용 (vscode에서 자동완성 지원)
  };
};
  • 사용하는 법
// src/App.js

import React from "react";
import { useDispatch, useSelector } from "react-redux";

// 사용할 Action creator를 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()); // 액션객체를 Action creator로 변경합니다.
        }}
      >
        + 1
      </button>
      {/* 빼기 버튼 추가 */}
      <button
        onClick={() => {
          dispatch(minusOne()); // 액션객체를 Action creator로 변경합니다.
        }}
      >
        - 1
      </button>
    </div>
  );
};

export default App;
  • dispatch()안에는 반드시 객체만 들어가야 한다고 알고 있는데, 어떻게 함수가 들어갈 수 있을까요?

    A. {type: “PLUS_ONE”} === plusOne() 는 같은 값입니다.
    함수를 실행한 것은 함수의 return 값

  • 왜 Action creator를 사용해야 하나?

    • (1) 휴먼에러 (오타) 방지

      액션객체의 type value를 상수로 만들어놓았기 때문에, 개발툴에서 자동완성등의 보조 기능을 지원받을 수 있습니다. 그래서 의도치 않은 휴먼에러(오타)를 없앨 수 있어요.

    • (2) 유지보수의 효율성 증가

      우리가 만든 Action Creator가 만약 100군데에서 쓰이고 있는 상태에서 혹여나 그것을 바꾸어야 하는 상황이 오더라도 단 한번의 수정으로 100군데에 모든 수정사항을 반영할 수 있습니다.

    • (3) 코드 가독성


    정리하자면

  • 액션객체를 만드는 함수를 Action Creator(액션 크리에이터)라고 한다.

  • Action Creator는 모듈 파일안에서 생성된다.

  • 액션객체의 type value로 상수로 생성해서 관리한다.

  • Action Creator를 사용하면, 여러가지 문제점을 해소할 수 있다.

출처: 항해99 reduxpart

profile
winwin
post-custom-banner

0개의 댓글