React기초(6) - Redux

joker·2020년 4월 13일
0

React

목록 보기
6/7


Redux 공식 홈페이지

Redux?

  1. javascript application의 state를 관리한다.
  2. Redux는 js 언어 모두 사용할수있다. 따라서 React에 100% 의존하는 Library가 아니다
  3. redux는 data를 관리하는것을 도와주기 위해 만들어졌다.

그렇기 때문에 먼저 vanilla js로 Redux를 사용해본 이후 React js로 Redux를 사용해보겠습니다.

준비물
html,css,vanilla js,react,react hook
visual studio code,npm,chrome,github

1. Repo 만들기

https://github.com 에 접속하여 새로운 repo를 만들어주세요.
[repo 만드는법을 모를시 이곳을 클릭]
(https://velog.io/@joker/React3)

2. CRA 만들기

create-react-app을 통해 새로운 app을 생성
CRA 만드는법을 모를시 이곳을 클릭

3. Clean up 하기

불필요한 파일은 삭제 필요 src 하위 directory에 index.js 만 냅두고 모두 지우기
index.js 모든 코드 삭제하고 github에 커밋하기

[commit 만드는법을 모를시 이곳을 클릭]
(https://velog.io/@joker/React3)

이제 본격적인 실습을 진행해 보겠습니다.

1. Vanilla JS 사용하기

public 하위 directory에 index.html이 현재 React 코드로 되어 있을 것입니다.
이곳을 아래의 코드로 수정해주세요

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>Vanilla Redux</title>
  </head>
  <body>
    <button id="add">Add</button>
    <span></span>
    <button id="minus">Minus</button>
  </body>
</html>

이후 npm start로 시작해 보면 아래와 같이 버튼이 생성되고 click시 아무 event가 발생되지 않을 것 입니다. 이제 src 하위 directory의 index.js의 수정이 필요합니다.

index.js

//html의 ID값 호출
const add = document.getElementById("add");
const minus = document.getElementById("minus");

const number = document.querySelector("span");

let count = 0;
number.innerText = count; //첫 화면 로딩시 0 노출

//해당 함수 호출시마다 count의 값을 number.innerText에 update함
const updateText = () => {
  number.innerText = count;
};

//html에게 무언가 변경되었다는 것을 알려주기 위해 함수를 사용
//
const handleAdd = () => {
  count = count + 1;
  updateText();
};

const handleMinus = () => {
  count = count - 1;
  updateText();
};

//click시 함수 호출
add.addEventListener("click", handleAdd);
minus.addEventListener("click", handleMinus);

이후 정상적으로 add와 minus가 작동 하는것을 확인 하실 수 있습니다.
Vanilla JS 코드 및 실행결과 보러가기

2. redux 사용하기

1. Store and Reducer

state -> App에서 바뀌는 data
store -> state를 넣는 곳, data를 넣을 수 있는 장소를 생성함
reducer -> 함수, data를 수정한다
redux는 data가 기본적으로 한곳에만 존재한다

redux 설치하기
npm install redux
해당 키워드를 통해 redux를 설치해주세요

index.js

import { createStore } from "redux";

const CountModifier = (state = 0) => {
  return state;
};

const countStore = createStore(CountModifier);

console.log(countStore.getState())

기본적인 redux 틀입니다.

  1. createStore로 store가 생성될시
  2. CountModifier(reducer)를 initial state로 불러오게 됩니다.
  3. 이것을 console.log로 해당 상태를 조회시 CountModifier에서 default로 설정해놓은 값인 0이 찍히는것을 확인 할 수 있습니다.

그럼 해당 store의 값을 어떻게 수정 할 수 있을까요? 답은 action에 있습니다.

2. Actions

index.js

import { createStore } from "redux";

const add = document.getElementById("add");
const minus = document.getElementById("minus");
const number = document.querySelector("span");

const CountModifier = (count = 0, action) => {
  console.log(action);
  return count;
};

const countStore = createStore(CountModifier);

countStore.dispatch({ type: "Hello" });

  1. store.dispatch({action})를 말하게 되면
  2. redux가 countModifier를 부르게 된다
    countModifier(currentState = 0,{type="Hello})
  3. message를 send 하는 방법은 dispatch를 이용하자

index.js

import { createStore } from "redux";

const add = document.getElementById("add");
const minus = document.getElementById("minus");
const number = document.querySelector("span");

const CountModifier = (count = 0, action) => {
  if (action.type === "Add") {
    return count + 1;
  } else if (action.type === "Minus") {
    return count - 1;
  } else {
    return count;
  }
};

const countStore = createStore(CountModifier);

countStore.dispatch({ type: "Add" });
countStore.dispatch({ type: "Add" });
countStore.dispatch({ type: "Add" });
countStore.dispatch({ type: "Minus" });

console.log(countStore.getState());

최초 count는 0,
3번의 Add action과 1번의 Minus action을 store에게 send 했기 때문에
countStore의 상태는 현재 2가 출력되고 있다.

위의 코드를 동적으로 변경하게되면 아래의 코드처럼 수정 할 수 있겠다. 이제 Add를 누르면 숫자가 증가하고 Minus를 누르면 숫자가 감소한다

하지만 Actions는 store를 update 하는것은 가능하지만 현재의 상태를 파악 하지는 못한다.
이런 이유로 subscribe를 사용한다

import { createStore } from "redux";

const add = document.getElementById("add");
const minus = document.getElementById("minus");
const number = document.querySelector("span");

const CountModifier = (count = 0, action) => {
  console.log(count, action);
  if (action.type === "ADD") {
    return count + 1;
  } else if (action.type === "MINUS") {
    return count - 1;
  } else {
    return count;
  }
};

const countStore = createStore(CountModifier);

const handlerAdd = () => {
  countStore.dispatch({ type: "ADD" });
};
const handlerMinus = () => {
  countStore.dispatch({ type: "MINUS" });
};

add.addEventListener("click", handlerAdd);
minus.addEventListener("click", handlerMinus);

3. Subscribe

store 안에 있는 변화들을 알 수 있게 해준다.

import { createStore } from "redux";

const add = document.getElementById("add");
const minus = document.getElementById("minus");
const number = document.querySelector("span");

number.innerText = 0;

const CountModifier = (count = 0, action) => {
  if (action.type === "ADD") {
    return count + 1;
  } else if (action.type === "MINUS") {
    return count - 1;
  } else {
    return count;
  }
};

const countStore = createStore(CountModifier);

const onChange = () => {
  number.innerText = countStore.getState(); 
};

countStore.subscribe(onChange);

const handlerAdd = () => {
  countStore.dispatch({ type: "ADD" });
};
const handlerMinus = () => {
  countStore.dispatch({ type: "MINUS" });
};

add.addEventListener("click", handlerAdd);
minus.addEventListener("click", handlerMinus);

store의 변화가 일어날때마다 subscribe(구독)을 통해 변화를 감지하고(onChange) 함수를 실행한다.
이로써 기본적으로 vanilla js를 통한 redux 사용방법에 대해 알아보았습니다.

4. conclusions(결론)

여태까지 작성한 코드와 정보를 살짝 정리해보면 아래와 같습니다.

  1. CountModifier는 현재 상태의 app과 함께 불려지는 function이다.

  2. 현재의 상태가 없다면 0으로 끝난다

  3. action은 countModifier과 소통하는 방법이다

  4. dispatch가 reducer(countModifier)를 불러서 current state와 우리가 보낸 action을 더한다.

  5. action은 object여야 한다.(string 금지)

  6. action은 type이 있어야 하는데 다른단어로 변경 불가하다

  7. store의 change를 감지하고 싶다면 subscribe를 사용해야 한다

위에서 마무리한 code는 Refactoring이 조금 필요합니다.. 필요한 것은

  1. if,else if,else문은 switch로 정리하면 훨씬 더 깔끔합니다.
const CountModifier = (count = 0, action) => {
  switch (action.type) {
    case "ADD":
      return count + 1;
    case "MINUS":
      return count - 1;
    default:
      return count;
  }
};
  1. 우리는 type을 string으로 사용하고 있는데 실수할 가능성이 높습니다. (add를 작성해야하는데 addd로 작성한다던지)
    이를 보완하기 위해 상수를 선언한 이후에 대입해줍니다.
  • 해당 상수도 잘못 적으면 어떻게하냐 똑같은거 아니냐 하실수도 있는데, 예를들어 dispatch의 type:MINUS가 아닌 type:MINS 라고 기재할 시에는 MINS define이라고 comepile 오류라고 명시해 주기 때문에 찾기 쉽습니다.
const ADD = "ADD";
const MINUS = "MINUS";

  switch (action.type) {
    case ADD:
      return count + 1;
    case MINUS:
      return count - 1;
    default:
      return count;
  }

const handlerAdd = () => {
  countStore.dispatch({ type: ADD });
};
const handlerMinus = () => {
  countStore.dispatch({ type: MINUS });
};

최종 코드 원본 보러가기

모두 수정하였다면 github에 commit후 push를 진행해주시기 바랍니다.

다음시간에는 React.redux에 대해 알아 보도록 하겠습니다.

profile
개발자입니다.

0개의 댓글