공부기록/[강의노트] Udemy React 완벽가이드 201~300

# 247 [udemy React 완벽 가이드 노트] 클래스 기반 컴포넌트가 있는 리덕스

Jenner 2022. 10. 12. 20:51

 

 

클래스 기반 컴포넌트를 만들자. 

그리고 메서드 incrementHandler와 decrementHandler와

toggleCounterHandler를 추가한다. 

 

어떻게 리덕스에 접근할 수 있는가?

 

class Counter2 extends Component {
  incrementHandler() {
    
  }
  decrementHandler() {
  }
  toggleCounterHandler() {

  }

  render() {
    return (
      <main className={classes.counter}>
        <h1>Redux Counter</h1>
        <div className={classes.value}>{counter}</div>
        <div>
          <button onClick={this.incrementHandler}>Increment</button>
          <button onClick={this.decrementHandler}>Decrement</button>
        </div>
        <button onClick={this.toggleCounterHandler}>Toggle Counter</button>
      </main>
    );
  }
}

 

 

함수 컴포넌트에서는 useDispatch와 useSelector 훅을 사용했었다.

훅은 클래스 컴포넌트에서는 사용할 수 없다. 

 

Connect 함수

 

react-redux는 connect 함수도 export한다. 

connect 함수는 클래스 기반 컴포넌트를 리덕스에 연결하는 데 도움을 준다. 

이것은 함수 컴포넌트에서도 사용할 수 있다. 

그러나 함수 컴포넌트에서는 훅을 사용하는 것들이 더 편리하다. 

 

 

사용방법

 

export default에 connect를 호출한다. 

connect가 실행되면 새 함수를 리턴한다.

그러면 컴포넌트를 변수로 리턴된 함수로 보내어 다시 실행된다. 

 

export default connect()(Counter);

 

왜 이렇게 하는걸까? 

이걸 실행할 때 연결하기 위해서 뭔가 보내기도 하는 것이다.

커넥트는 두개의 함수로 된 인자가 있어야 한다. 

 

 

첫 번째 인자는 

 

 

 

컴포넌트에 받아질

리덕스 state를 프롭으로 맵하는 함수다. 

 

리덕스 state를 받아서 객체를 리턴하고 

받는 컴포넌트에서(여기서는 Counter) 키를 프랍으로 사용할 수 있다. 

키의 값은 리덕스 state로 들어가는 로직이다. 

 

const mapStateToProps = state => {
  return {
    counter: state.counter 
  }
}

리덕스 state에서 counter값을 선택, 

그 값을 카운터 프롭에 묶는다. 

 

 

useSelector에서 한 것과 비슷하다. 

state를 받고 counter를 받기 위해 state로 들어간다. 

  const counter = useSelector(state => state.counter);

 

훅이 아니라 커넥트 함수일 뿐, 두가지는 같은 일을 하고 있다. 

 

 

이제 커넥트로 보내는 첫 번째 인자로 mapStateToProps를 보낸다. 

 

export default connect(mapStateToProps)(Counter);

 

 

두 번째 인자는

 

 

useDispatch와 같은 역할을 하는 또다른 함수다.

디스패치 함수를 프랍에 저장하는 것이다. 

 

Counter컴포넌트에 특정 프랍을 입력하고, 

액션을 리덕스 스토어에 디스패치 해 

함수로 실행할 수 있게 한다. 

 

 

const mapDispatchToProps = () => {
  
}

 

 

여기서 자동으로 mapStateToProps처럼

디스패치 함수를 인자로 받는다. 

 

mapDispatchToProps함수는

리덕스가 우리를 위해 실행 해 줄 것이다. 

 

이 함수는 객체를 return하는데, 

 

키는 프랍네임인데

컴포넌트에서 사용할 수 있다.

 

밸류는 다른 함수인데

디스패치를 입력하여 액션을 설정한다.

 

 

 

const mapDispatchToProps = dispatch => {
  return {
    increment: ()=> dispatch({type: 'increment'}),
    decrement: ()=> dispatch({type: 'decrement'})
};

 

 

 

이렇게 되면 Counter  컴포넌트에서 increment 프롭이 있어 사용할 수 있게 된다. 

increment 프롭은 함수를 저장하고 있고,

컴포넌트 내부에서 이 함수를 실행할 수 있다. 

 

그러면 dispatch를 호출하여 

 

 

 

{type: 'increment'}

 

위의 액션을 dispatch하게 된다.

 

이 함수가 connect에 보낸 두 번째 인자다. 

 

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

이렇게 두가지를 포인터로 보내주면(실행 아님)

react-redux가 우릴위해 실행하게 될 것이다. 

 

 

커넥트를 사용하면 

react-redux가 subscription을 설정하고 관리해 줄 것이다. 

 

 

class Counter2 extends Component {
  incrementHandler() {
    this.props.increment();
  }
  decrementHandler() {
    this.props.decrement();
  }

 

incrementHandler 메서드에서 this.props.increment로 실행할 수 있다. 

 

 

 

Counter.js파일

 

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

import classes from "./Counter.module.css";

class Counter extends Component {
  incrementHandler() {
    this.props.increment();
  }
  decrementHandler() {
    this.props.decrement();
  }
  toggleCounterHandler() {}

  render() {
    return (
      <main className={classes.counter}>
        <h1>Redux Counter</h1>
        <div className={classes.value}>{this.props.counter}</div>
        <div>
          <button onClick={this.incrementHandler.bind(this)}>Increment</button>
          <button onClick={this.decrementHandler.bind(this)}>Decrement</button>
        </div>
        <button onClick={this.toggleCounterHandler}>Toggle Counter</button>
      </main>
    );
  }
}

const mapStateToProps = state => {
  return {
    counter: state.counter,
  };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: "increment" }),
    decrement: () => dispatch({ type: "decrement" }),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Counter);