7. Redux: react-redux | 컴포넌트에서 사용하기

  • 뷰 바인딩 도구
  • 리액트 컴포넌트에서 redux를 사용하면 복잡한 작업을 해 준다.

Provider

: 컴포넌트에서 redux를 사용하도록 서비스 제공. Provider는 하나의 컴포넌트이다.

import { Provider } from 'react-redux';

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

connect([...options])

  • 컴포넌트를 redux에 연결하는 함수를 반환.
  • connect()(Counter) : store에 연결 된 새로운 컴포넌트 클래스가 반환됨. 옵션이 없으면 this.props.store로 접근 가능.
  • [mergeProps] 잘 사용하지 않음
  • [options] {[pure = true], [withRef = false]}
connect(
    [mapStateToProps],
    [mapDispatchToProps],
    [mergeProps],
    [options]
)
// App.js
import React, { Component } from 'react';
import Counter from './Counter';

class App extends React.Component {
    render() {
        return (
            <Counter />
        );
    }
}

export default App;
// Control.js
import React, { Component, PropTypes } from 'react';

const propTypes = {
    onPlus: PropTypes.func,
    onSubtract: PropTypes.func,
    onRandomizeColor: PropTypes.func
};

function createWarning(funcName) {
    return () => console.warn(funcName + ' is not defined');  //기본값 : 함수가 설정 되지 않았다고 경고를 띄움
}

const defaultProps = {
    onPlus: createWarning('onPlus'),
    onSubtract: createWarning('onSubtract'),
    onRandomizeColor: createWarning('onRandomizeColor')
};

class Control extends React.Component {
    render() {
        return (
            <div>
                <button onClick={this.props.onPlus}>+</button>
                <button onClick={this.props.onSubtract}>-</button>
                <button onClick={this.props.onRandomizeColor}>Randomize Color</button>
            </div>
        );
    }
}

Control.propTypes = propTypes;
Control.defaultProps = defaultProps;

export default Control;
// Counter.js
import React, { Component, PropTypes } from 'react';

import Value from './Value';
import Control from './Control';
// import { connect, bindActionCreators } from 'react-redux';
import { connect } from 'react-redux';

import * as actions from '../actions';

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.setRandomColor = this.setRandomColor.bind(this);
    }

    setRandomColor() {
        const color = [
            Math.floor((Math.random()*55) + 200),
            Math.floor((Math.random()*55) + 200),
            Math.floor((Math.random()*55) + 200)
        ];

        this.props.handleSetColor(color);
    }

    render() {

        const color = this.props.color;
        const style = {
            background: `rgb(${color[0]}, ${color[1]}, ${color[2]})`
        };

        return (
            <div style={style}>
                <Value number={this.props.number}/>
                <Control
                    onPlus={this.props.handleIncrement}
                    onSubtract={this.props.handleDecrement}
                    onRandomizeColor={this.setRandomColor}
                />
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        number: state.counter.number,
        color: state.ui.color
    };
};

const mapDispatchToProps = (dispatch) => {
    // return bindActionCreators(actionCreators, dispatch);

    return {
        handleIncrement: () => { dispatch(actions.increment()) },
        handleDecrement: () => { dispatch(actions.decrement()) },
        handleSetColor: (color) => { dispatch(actions.setColor(color))}
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(Counter);
// Value.js
import React, { Component, PropTypes } from 'react';

const propTypes = {
    number: PropTypes.number
};

const defaultProps = {
    //기본값
    number: -1
};

class Value extends React.Component {
    render() {
        return (
            <div>
                <h1>{this.props.number}</h1>
            </div>
        );
    }
}

Value.propTypes = propTypes;
Value.defaultProps = defaultProps;

export default Value;

code & view