Application/JS-React

초보자를 위한 리덕스 101

winney916 2022. 5. 22. 13:58
728x90

리액트 에러

You are running `create-react-app` 4.0.3, which is behind the latest release (5.0.0). 

npx create-react-app project_name : 에러발생

->  create-react-app@latest로 변경해주면 해결된다. 최신버전을 사용해달라는 의미인듯?

 

npm ERR! Cannot read property 'pickAlgorithm' of null

: 아우 왜 자꾸 앱 만드는데서 에러가 나는지 의문이다...

-> 그냥 캐쉬 지우면 된다고 한다.  The only thing that helped me was clearing cache:

npm cache clear --force

Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.

: React-Router-Dom 버전에러이다. 최신 버전에서 문법이 좀 변경되었는데 이를 지켜주지 않아서 그렇다.

그래서 버전 다운그레이드를 진행했다.

yarn add react-router-dom@5.3.0

 

 

리덕스를 사용하는 이유

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

let count = 0;
number.innerText = count;

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

add.addEventListener("click", handleAdd);
minus.addEventListener("click", handleMinus);

다음과 같은 js를 구현했다고 했을 대, 버튼들의 클릭이 실제 number라는 span값에 반영되지 않는다.

number.innerText=count를 초기에만 진행했기 때문인데 버튼 클릭 함수를 해당 값에 반영하기 위해서는 변경이 발생할 때마다 값을 갱신해줘야한다.

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

let count = 0;
number.innerText = count;

const updateText = () => {
  number.innerText = count;
};

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

add.addEventListener("click", handleAdd);
minus.addEventListener("click", handleMinus);

위와같은 형태의 일들을 처리해주는게 Redux라고 할 수 있다.

 

 

ORIGINAL REDUX with VanillaJS

시작하기

yarn add redux

학교 수업으로 인해 yarn을 사용하게됐다. npm add redux해도 된다.

 

import { createStore } from "redux";

createStore : state를 app 상에 holding해주는 역할을 한다.

 

Store : State를 보관하는 곳

State : 앱 내에서 변경되는 데이터이다. (hooks에서 사용하는 useState가 바로 이것)

 

기본적인 구조는 다음과 같다.

const reducer = (state = INITIAL_VALUE, action) => {
	if (object.type == "Something"){
    	// do something
    }
    return state;
}
const store = createStore(reducer);
console.log(store.getState());
store.dispatch(object);

const onChange = () => {
	// do something
}
store.subscribe(onChange);

- reducer : state와 action parameter를 받아서 state를 변경해주는 함수이다. return 값이 store 내부의 state가 된다고 생각하면 된다. store 생성시에는 createStore인자로 reducer 함수가 들어가면 된다.

  (docs 설명) 

    - state : 현재 상태 저장 객체 (useState에서의 state 맞다.)

    - action : state에 어떤 일이 일어났는지를 저장하는 객체. action을 이용해 state를 갱신한다.

 

APIs : 3개의 api가 존재한다.

- getState() : state값을 반환한다.

 

- dispatch(object) : 아주 중요하다. object를 보내주는데 이를 reducer함수에서 action으로 받는다. 해당 object에 접근해 데이터를 사용하고 state를 수정한다. reducer상에 action객체로 state의 변화 내용을 전달하는 유일한 방법이다. store.dispatch(object)하게되면 object가 reducer함수에서 action객체로 전달된다.

 

- subscribe(function) : state가 변할 떄마다 호출되는 함수이다.  state의 변화를 통해서 다른 값들을 갱신해줘야 할 때 / State의 변화를 UI에 반영해야 할 때 사용하면 된다. useEffect같은 느낌이다.

 

요약하면, getState로 state 전달받고, dispatch로 갱신한 다음 subscribe로 갱신 후 작업을 진행하면 된다.

 

주의할 점

Don't mutate

: 절대 객체를 수정하면 안된다.

 array.push(data) -> X

 [...array, data] => O

 

 늘 이렇게 새로운 객체를 반환하는 형태로 진행해야한다.

 mutate State가 아닌 make New State로 이해하라!!

 

 

 

 

 

React-Redux

시작하기

 

yarn add react-redux react-router-dom

redux 상에서의 subscribe함수는 변화된 데이터 전부를 전달한다. 하지만 리액트는 변화하는 (추가 혹은 삭제) 데이터만 전달한다는 점에서 상충하는 부분이 생긴다.

react-redux가 필요해지는 순간이다.

 

setting

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import App from "./components/App";
import store from "./store";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

index.js 부분에서 Provider 태그에 App을 상속시키고 Provider에 store를 인자로 전달한다.

 

API Reference

Provider

 : Redux store를 app에서 사용할 수 있도록 만들어주는 component이다. <App/>을 상속시키면 된다. 그리고 속성으로  store를 넣어주면 된다.

 

 

Hooks

 : 리액트-리덕스는 커스텀 훅을 제공한다. react component가 redux store와 상호작용 할 수 있게된다.

 

- useSelector : store의 state와 업데이트를 위한 subscriber를 불러온다.

- useDispatch : 스토어의 dispatch 메서드를 리턴하여 action을 알려준다.

 

근데 니꼬썜은 안쓰셨다.

 

Connect

 : React component 를 Redux Store에 저장한다. 스토어에 저장된 데이터와 연결된 컴포넌트를 만든가고 생각하면 된다. 

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)(MyComponent)

 - mapStateToProps :  connect 함수의 첫 번째 인자.  subscriber라고 보면 된다.

                                    store 내부의 state에 변화가 생길 때마다 호출되는 함수이다.

        두 개의 파라미터를 받는다.

            - state : store에 저장되어있는 state이다.

            - ownProps :  props가 전달되는 파라미터이다.

       return value :  object를 반환한다. 이 object는 연결된 컴포넌트(MyComponent)로 전달된다.

 

 - mapDispatchToProps : 두 번째 인자이다. dispatch를 수신한다.

 

        두 개의 파라미터를 받는다.

            - dispatch : redux에서 봤던 dispatch 함수이다. 여기에 인자를 전달하여 store상의 reducer가 작동하도록 한다.

            - ownProps : props가 전달된다.

 

Batch()

 :  batch 라는 api가 존재하지만 아직 경험이 없다.