본문 바로가기
Today I learned

[react] 3 주차 redux (2)

by soheemon 2020. 2. 1.

Optimize

 

+ 외국에서는 JPA를 많이 씀

+ REST + Spring Boot

+ TypeORM + Node + TypeScript

 

Redux 시작

reduce: pureFunction 비동기- 같은것이 없는 통신을 안하는, 함수.

 

*부모와 자식간에 통신이 그 단계가 길어지게 되면 여러번 통신을 하게 된다.

 redux를 사용하게 되면 store에 그 데이터를 저장하고 읽을 수 있으므로 여러단계의 통신을 한단계로 줄일수 있게 된다.

 

*redux는 리액트와 관련없는 순수한 3rd party 라이브러리이다.

react-redux는 redux를 react에 적용한 라이브러리이다. 

 

reducer를 생성하기 위해서는 function이 필요하고 이 function이 return하는것으로 초기 state가 만들어진다.

reducer: mutate라고 하기도 함. 상태를 변경하는자..?

 

action을 받아서 상태를 변경 한 후 변경된 상태를 state에 저장한다. (변경된 상태를 반영하기때문에 변형자-라고 하기도 한다.)

 

이 그림을 이해하도록 하자.

 

 

* 워크스페이스에 새로운 react-app 생성

 

 

# redux 설치
npm i -S redux

 

*공용 저장소 만들기

//store

 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {createStore} from "redux"

//state를 변경하는방법은 1) setState 2)Action을 disPath한다-
const reducer = (state, action) => {
    if(action.type === 'changeState'){
        return action.payload;
    }
    return 'State'; //reduce가 return한 것이 초기값을 구성한다.
}

const store = createStore(reducer); //초기화
console.log(store.getState());

/*가입구독 디자인패턴*/
//1) 가입한다 3) 변경된 데이터 수신
store.subscribe(() => {console.log(store.getState())}); //상태변경시 호출됨
const action = {
    type: 'changeState',
    payload: 'New State'
}
//2. 상태를 변경한다
store.dispatch(action);         //action을 dispatch한다.

ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();

 

결과

 

 

getState: state를 꺼낼수 있다.

콘솔화면에 store가 dispatch, subscribe, getState, replaceReducer 등 여러가지 메서드가 보일것이다. store.getState()를 출력하면 reducer 펑션을 실행하고 리턴된 “State” 라는 초기 state를 볼 수 있다.

 

Action

객체다-

ActionType: stringType

 

dedux DevTools

 

 

현재 State상태를 알 수 있다...

 

* 두개의 reducer를 합치자.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {combineReducers, createStore} from "redux"

//default parameter라는 문법. 왜냐 초기 state를 넣어주지 않아서 undefineded가 선언되기 때문.
const productReducer = (state = [], action) => {
    return state;
}

const userReducer = (state, action) => {
    return state;
}
//두가지 reducer 결합 => combineReducers. param은 결합할 reducer를 넣는다.

const allRecucers = combineReducers({
    product: productReducer,
    user : userReducer
})
//만약 productReducer, userReducer로 쓴다면 shorthand property가 되여서 키가 NAME이 된다 ES6문법

const store = createStore(allRecucers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
console.log(store.getState());

/*가입구독 디자인패턴*/
//1) 가입한다 3) 변경된 데이터 수신
store.subscribe(() => {console.log(store.getState())}); //상태변경시 호출됨
const action = {
    type: 'changeState',
    payload: 'New State'
}
//2. 상태를 변경한다
store.dispatch(action);         //action을 dispatch한다.

ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();

 

Action도 변경해보기

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {combineReducers, createStore} from "redux"

//default parameter라는 문법. 왜냐 초기 state를 넣어주지 않아서 undefineded가 선언되기 때문.
const productReducer = (state = [], action) => {
    return state;
}

const userReducer = (state = '', action) => {
    switch(action.type){
        case 'updateUser':
            return action.payload;
    }
    return state;
}
//두가지 reducer 결합 => combineReducers. param은 결합할 reducer를 넣는다.

const allRecucers = combineReducers({
    product: productReducer,
    user : userReducer
})

const store = createStore(allRecucers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
console.log(store.getState());

/*가입구독 디자인패턴*/
//1) 가입한다 3) 변경된 데이터 수신
store.subscribe(() => {console.log(store.getState())}); //상태변경시 호출됨
const action = {
    type: 'updateUser',
    payload: 'Tom'
}
//2. 상태를 변경한다
store.dispatch(action);         //action을 dispatch한다.

ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();

요약

+ redux는 프레임웍이다.

+ Publisher – Subscriber 구조로 action을 dispatch 하는것은 publish에 해당하고 publish 전에 변경된 상태를 읽을 필요가 있으면 먼저 subscribe 해야 한다.

+ store 는 single source를 갖고 있다.

+ store가 처음 생성되면 reducer를 실행해서 state를 초기화 한다.

+ action type 은 스트링이다.

+ action은 객체이다.

+ action creator 는 액션을 생성하는 함수이다.

+ reducer는 순수한 펑션으로 이루어져 있다.

+ action을 dispatch 하면 store에 reducer가 실행되고 reducer는 state, action을 입력으로 받아서 새로운 state를 생성한다.

+ store의 state를 바꾸는 방법은 action을 dispatch하는 방법밖에 없다.

 

React-Redux 시작

 

이제 redux에서 생성한 store를 리액트에 어떻게 주입하고 subscribe 와 publish (action dispatch)를 리액트에서 어떻게 하는지 살펴보자.

- Provider라는 컴포넌트를 주입한다.

App을 그 안에 넣어준다.

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

모듈화

하나의 파일안에 만들었던 redux들을 여러개의 파일로 나눈다.

 

 

 

+ 곁다리

ctrl + alt + O 사용하지 않는 모듈 삭제-

* 응집도를 높힌다-

* low디커플링: 패키지내에서는 다른 패키지를 참조하지 말라. 내부의 패키지만 참조하라-

 

부모 -> 자식간의 통신: subscribe

react에서 부모가 자식에게 통신하기 위해서 props를 내려주었다. 만일 자식이 바로 아래있는 자식이 아니라면 연속해서 내려주어야 했다. 

이제 이 부분은 store => 자식 간의 통신으로 store에서 자식컴포넌트로 바로 내려주도록 변경된다.

아래는 props의 user와 store의 state.user를 연결하였다. 이제 store의 products와 user가 변경되면 props를 통해서 업데이트 받을수 있다.

import React from 'react';
import logo from './logo.svg';
import './App.css';
import {connect} from "react-redux";

function App(props) {
  console.log(props);

  return (
    <div className="App">
      <p>product length: {props.aaa.length}</p>
      <p>{props.bbb}</p>
    </div>
  );
}

// subscribe: 부모와 자식간의 통신
// 규칙 1) Score의 State를 props로 맵핑한다. 쉽게말하면 모든 state는 store로부터 내려받는것임.
// score로부터 props로 내려받는다.
const mapStateToProps = (state) => {
  return {
    // 왼쪽은 props, 오른쪽은 store의 state가 와야한다.
    aaa: state.productReducer,
    bbb: state.userReducer
  }
}
// Hoc, 커링펑션을 알아야 한다.
export default connect(mapStateToProps)(App);

*정신줄을 놨기때문에 이코드를 1도 이해하지 못했다. 복습이 필요하다...

 

Hook을 쓰면 간편하게 사용할 수 있다.

댓글