개발/react

connect

kwony 2020. 12. 20. 11:08

connect 함수는 리액트 앱의 하위 컴포넌트에서 redux store를 접근하는 것을 가능하게 해주는 역할을 한다. 이 함수를 이용해서 컴포넌트 단에서 redux store에 접근하고 액션을 호출 할 수 있게 된다. 이번 포스트에서는 간단한 예제로 connect 함수를 통해 redux store를 사용하는 방법을 다뤄보려고 한다.

 

0. 준비작업

 

connect 함수 소개를 위해 예제와 텍스트와 숫자를 담당하는 redux를 만들었다.

 

BlogStore.js

import { createStore, combineReducers } from 'redux';

const textReducerState = {
    text: '',
    name: 'textReducer'
};

const textReducer = (state = textReducerState, action) => {
    switch (action.type) {
        case 'SET_TEXT':
            return {
                ...state,
                text: action.text
            };
        default: 
            return state;
    }
}

const numberReducerState = {
    numberState: 30,
    name: 'numberReducer'
};

const numberReducer = (state = numberReducerState, action) => {
    switch (action.type) {
        case 'SET_NUMBER':
            return {
                ...state,
                number: action.number
            };
        default: 
            return state;
    }
};

export const configureStore = () => {
    const store = createStore(
        combineReducers({
            text: textReducer,
            number: numberReducer
        })
    );
    return store;
};

 

BlogActions.js

 

export const setText = (
    text = ''
) => ({
    type: 'SET_TEXT',
    text
});

export const setNumber = (
    number = 0
) => ({
    type: 'SET_NUMBER',
    number
});

 

 

1. Provider 

 

configureStore() 함수를 통해 store를 생성하고 Provider 태그에 store를 속성값으로 넣는다. 이러면 하위에 추가되는 component에서 redux store를 바라볼 수 있는 창구가 만들어진다.

 

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { configureStore } from './BlogStore';
import BlogMain from './BlogMain';

const store = configureStore();


const jsx = (
    <Provider store={store}>
        <BlogMain />
    </Provider>
);


ReactDOM.render(jsx, document.getElementById('app'));

 

2. connect 

 

하위 컴포넌트 단에서는 Provider에서 제공하는 store 함수를 connect 함수를 통해서 받아온다. 함수 형식이든 클래스 형식이든 받는 방식은 동일하다. 

 

 

2.1 클래스형식

 

import React from 'react';
import { connect } from 'react-redux';
import BlogDetail from './BlogDetail';


class BlogMain extends React.Component {
    render() {
        console.log(this.props.text)
        console.log(this.props.number)
        return (
            <div>
                <p>BlogMain component</p>
                <BlogDetail />
            </div>
        )
    };
};
const mapStateToProps = (state) => {
    return {
        text: state.text,
        number: state.number
    }
};
export default connect(mapStateToProps)(BlogMain);

 

클래스 형식 컴포넌트를 export 할 때 connect 함수를 사용하고 첫번째 인자에 mapStateToProps 함수를 넣었는데 redux store에 있는 값을 컴포넌트에 어떻게 넘겨줄지 세팅하는 작업이다.  넘겨 받은 값은 component의 props에 들어가서 호출 할 수 있다. 아래 사진은 render() 함수 안에서 console로 찍은 로그다. textReducer와 numberReducer가 출력되는 것을 볼 수 있다.

 

 

2.2 함수 형식 

 

import React from 'react';
import { connect } from 'react-redux';

const BlogDetail = (props) => (
    <div>
        <p>BlogTextDetail</p>
        <p>{props.text.name}</p>
    </div>
);
const mapStateToProps = (state) => {
    return {
        text: state.text
    };
};

export default connect(mapStateToProps)(BlogDetail)

 

함수 형식도 크게 다르지 않다. 컴포넌트 내에서 호출 할 때 this를 부르지 않아도 된다는 점만 다르다. 위 코드로 호출하면 아래 그림처럼 화면 뷰가 그려진다.

 

 

3. Action 

 

connect로 컴포넌트에 전달 할 때 store만 전달 하는것이 아니라 action을 넣을 수 있는 dispatch 함수까지 전달된다. react 디바이스 툴을 사용해보면 component의 props 안에 dispatch가 들어있는 것을 확인 할 수 있다. 

 

 

실제로도 잘 사용할 수 있을 지 테스트 해보자. 방금 전에 사용한 BlogDetail 컴포넌트를 살짝 수정해서 현재 store에 저장된 text를 출력하고 버튼을 추가하고 클릭하면 text를 BlogDetail로 바뀌도록 했다.

 

import React from 'react';
import { connect } from 'react-redux';
import { setText } from './BlogActions';

const BlogDetail = (props) => (
    <div>
        <p>BlogTextDetail</p>
        <p>current store text value: {props.text.text}</p>
        <button onClick={() => {
            props.dispatch(setText('BlogDetail'))
        }}>Change text to BlogDetail</button>
    </div>
);

const mapStateToProps = (state) => {
    return { text: state.text};
};

export default connect(mapStateToProps)(BlogDetail)

 

함수를 실행하고 버튼을 클릭하니 화면이 아래와 같이 store의 text 값이 BlogDetail로 변경됐다.

 

 

4. 총평 

 

코딩을 처음 하는 분이면 이걸 왜 이렇게까지 해야할지 이해가 안될 수 있을 것 같은데 이전에 mvvm, mvc 패턴을 경험해본 개발자들에게는 redux가 크게 어려울 것 같지 않다. 강의 들을 때는 헷갈렸는데 실제로 코드로 짜보니까 어떤 식으로 구조를 잡아야할 지 느낌이 온다. 물론 자바스크립트 언어 특성상 state 세부 이름을 관리할 때 꽤 귀찮음을 겪을 것 같긴 하다.