티스토리 뷰

WEB/Reat

Redux(2)

취뽀가자!! 2019. 1. 12. 16:59

Redux

리덕스의 3가지 규칙

1. 하나의 애플리케이션 안에는 하나의 스토어가 있다.

하나의 애플리케이션에서는 단 한 개의 스토어를 만들어 사용한다. 여러개의 스토어를 사용하는 것이 가능은 하지만 권장하지 않는다. 특정 업데이트가 너무 빈번하게 일어나거나, 애플리케이션의 특정 부분을 완전히 분리시키게 될 때 여러개의 스토어를 만들 수도 있다. 하지만 이럴 경우 개발 도구를 활용하지 못하게 된다.

2. 상태는 읽기 전용이다.

리액트에서 state를 업데이트 할 때, setState를 사용하고, 배열을 업데이트 해야 할 대는 배열 자체에 push를 직접 하지 않고, concat같은 함수를 사용하여 기존의 배열은 수정하지 않고 새로운 배열을 만들어서 교체하는 방식으로 업데이트를 한다. 엄청 깊은 구조로 되어있는 객체를 업데이트 할 때도 마찬가지로 기존의 객체는 건들이지 않고 Object.assign을 사용하거나 spread연산자인 ...을 사용하여 업데이트를 한다.

리덕스에서도 마찬가지로 기존의 상태는 건들지 않고 새로운 상태를 생성하여 업데이트 해주는 방식으로 해주면, 나중에 개발자 도구를 통해서 디로 돌릴 수도 있고 다시 앞으로 돌릴 수도 있다.

리덕스에서 불변성을 유지해야 하는 이유는 부분적으로 데이터가 변경되는 것을 감지하기 위해 shallow equality검사를 하기 때문이다. 이를 통해 객체의 변화를 감지 할 때 객체의 깊숙한 안쪽까지 비교를 하는 것이 아니라 겉핥기 식으로 비교를 하여 좋은 성능을 유지할 수 있다.

3. 리듀서는 순수한 함수이어야 한다.

순수한 함수라는 개념은 다음 사항을 기억해주면 된다.
  • 리듀서 함수는 이전 상태와, 액션 객체를 파라미터로 받습니다.
  • 이전의 상태는 절대로 건들이지 않고, 변화를 일으킨 새로운 상태 객체를 만들어서 반환합니다.
  • 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과값을 반환해야만 합니다.
위 3가지 사항을 주의해야 한다. 동일한 인풋이라면 언제나 동일한 아웃풋이 있어야 한다. 그런데 일부 로직들 중에서는 실행 할 때마다 다른 결과값이 나타날 수도 있다. 
그러한 작업들은 리듀서 함수의 바깥에서 처리해줘야 한다. 그런것들을 하기 이해서 리덕스 미들웨어를 사용하곤 한다.

Provider

리액트 프로젝트에 스토어를 연동 할 때에는 react-redux라이브러리 안에 들어있는 Provider라는 컴포넌트를 사용한다. 기존의 JSX를 Provider로 감싸고, store는 props로 Provider한테 넣어주면 된다.
<Provider store={store}>
    <App />
  </Provider>

connect

리덕스와 연동된 컴포넌트를 컨테이너 컴포넌트라 하고, 단순히 props를 전달해주면 그대로 보여주는 컴포넌트들을 프리젠테이션 컴포넌트라 부른다.

컨테이너 컴포넌트는  Smart컴포넌트, 프리젠테이셔널 컴포넌트는 Dumb 컴포넌트라고 부르기도 한다.

이런 개발 방식의 최대 장점은 프리젠테이셔널 컴포넌트에서느는 UI의 모양새에만 집중 할 수 있고, 컨테이너 컴포넌트쪽에서는 유저 인터랙션쪽에 집중 할 수 있다는 점이 있다.
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Palette from '../components/Palette';
import { changeColor } from '../store/modules/counter';

class PaletteContainer extends Component {
  handleSelect = color => {
    const { changeColor } = this.props;
    console.log('what');
    changeColor(color);
  };

  render() {
    const { color } = this.props;
    return <Palette onSelect={this.handleSelect} selected={color} />;
  }
}

// props 로 넣어줄 스토어 상태값
const mapStateToProps = state => ({
  color: state.counter.color,
});

// props 로 넣어줄 액션 생성함수
const mapDispatchToProps = dispatch => ({
  changeColor: color => dispatch(changeColor(color)),
});

// 컴포넌트에 리덕스 스토어를 연동해줄 때에는 connect 함수 사용
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(PaletteContainer);

컨테이너 컴포넌트를 만들 때는 react-redux안에 들어있는 connect라는 함수를 사용한다. 이 함수는 파라미터에 전달해주는 mapStateToProps는 스토어 안에 들어있는 값을 props로 전달해주고, mapDispatchToProps는 액션 생성함수들은 props로 전달해준다.


여기서 mapDispatchToProps가 조금 헤갈릴 수도 있는데, 액션 생성함수는, 호출한다고 해서 상태에 변화가 일어나는 것이 아니다. 그 대신에, 액션 객체를 생성해난다. 그 액션 객체를 스토어한테 전달해주어야 상태에 변화가 발생한다.


여기 있는 mapDispatchToProps에서는 color를 파라미터로 받아와서 그 값을 가지고 CHANGE_COLOR액션 객체를 생성한 다음에 스토어한테 디스패치 하는 함수를 컴포넌트의 props로 전달해 주는 것이다.



connect함수가 호출되면 반환되는 값은 특정 컴포넌트에 설정된 props를 전달해 주는 함수이다. 지금은 connect(...)(PaletteContainer)ㅇ이런식으로 호출되었는데, connect()를 호출해서 반환받은 함수에, PaletteContainer를 파라미터로 넣어서 호출한 것이라고 이해하면 된다.


bindActionCreators

dispatch를 계속해주기가 귀찮으면 bindActionCreators라는 함수를 사용하면 조금 더 쉽게 할 수 있다.

const mapDispatchToProps = dispatch =>
  bindActionCreators({ changeColor1, changeColor2, ... }, dispatch);

이렇게 하면 기존해 했던 actionCreator: (...params) => dispatch(actionCreator(...params)에 해당하는 작업을 자동으로 해 준다. 만약에 액션 생성함수가 파라미터를 필요로 하는것이더라도, 정상적으로 작동한다.


또 다른 방식으로는 mapDispatchToProps를 함수형태가 아닌 액션생성함수로 이뤄진 객체를 전달해주면 connect가 발생하게 될 때 bindActionCreators를 자동으로 해 준다.


const mapDispatchToProps = { changeColor1, changeColor2, .... };

combineReducers

리듀서가 여러개인 경우에는 redux의 내장함수인 combineReducer을 사용하면 여러 개의 리듀서를 합칠 수 있다. 여러개의 리듀서를 서브리듀서라고 하고, 하나로 합쳐진 리듀서를 루트리듀서라고 한다.
import { combineReducers } from 'redux';
import counter from './counter';

export default combineReducers({
  counter,
  // 다른 리듀서를 만들게되면 여기에 넣어줌..
});
{
  counter: {
    // counter에서 사용하는 초깃값
  },
  // ... 다른 리듀서에서 사용하는 초깃값들
}


'WEB > Reat' 카테고리의 다른 글

Block Update  (0) 2019.01.23
Middle Ware  (0) 2019.01.13
Redux(1)  (0) 2019.01.12
CRA(Create rReact App)  (0) 2019.01.08
React 간단 정리  (0) 2018.12.14
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함