본문으로 바로가기

  

[redux란?]

redux는 컨텍스트와 마찬가지로 데이터를 필요한 컴포넌트에서만 요청해 사용할 수 있습니다. 컨텍스트는 부모 컴포넌트에서 생성한 데이터에 모든 자식 컴포넌트에서 접근할 수 있습니다. 하지만 redux에서는 컴포넌트 외부의 스토어라는 곳에서 관리합니다. 그래서 컴포넌트의 위치에 상관없이 스토어에 접근해 데이터를 사용하고 변경할 수 있습니다. redux는 데이터를 스토어 > 컴포넌트 > 액션 > 리듀서 > 스토어의 과정을 통해 변경합니다. 

 

[redux 세팅]

혹시 redux가 설치가 안되어 있다면, cmd 창을 열어 작업하고 계신 프로젝트 경로로 이동해서 아래 명령어를 입력하면 설치가 완료됩니다.

npm install --save redux

 

 

[예제]

예제를 통해서 어떤 식으로 동작하는지 알아보도록 하겠습니다.

reducer에서 action에 작성된 내용을 읽어 store에 저장되어있는 data에 100씩 추가해보는 예제입니다.

 

파일 구조

src actions index.js
  reducers index.js
  index.js  
  App.js  
  StrAddButton.js  

 

src ➡️ index.js (src 폴더의 index.js)

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {createStore} from 'redux';
import reducers from './reducers';

// createStore 함수의 파라미터로 reducers 폴더 경로를 넘김
const store = createStore(reducers);

const listener = () => {
  ReactDOM.render(
    // App.js 에 props 데이터로 store 전달
    <App store={store}/>,
    document.getElementById('root')
  );
};

// 구독을 해야 store 데이터에 변화가 있을 때 listner 함수의 render를 실행하고 변경된 데이터를 렌더링
store.subscribe(listener);

// render 함수를 listner 함수로 감쌌기 때문에 초기 렌더링을 위해 수동으로 render
listener();

 

src ➡️ App.js (src 폴더의 App.js)

props에 스토어를 담아 하위 컴포넌트로 전달하면, 전달받은 컴포넌트에서 스토어에 접근할 수 있습니다.

컴포넌트에서 dispatch 함수를 사용하면 스토어 데이터를 변경할 수 있습니다.

import React, { Component } from 'react';
import StrAddButton from './StrAddButton';
import './App.css'

class App extends Component {
  render() {
    return(
      <div className="App-header">
        <h2>value: {this.props.store.getState().data.str}</h2>
        <br/>
        <StrAddButton store={this.props.store}/>
      </div>
    )
  }
}

export default App;

 

src ➡️ StrAddButton.js (src 폴더의 StrAddButton.js)

dispatch 함수는 리듀서에 액션을 전달하고 리듀서에서는 액션의 작업 내용을 토대로 스토어 데이터를 변경합니다.

import React, {Component} from 'react';
import {add} from './actions';

class StrAddButton extends Component {
    render() {
        return(
            <input value="+100" type="button" onClick={this.addString} />
        )
    }

    addString = () => {
        // dispatch 함수를 통해 add 함수의 반환 값을 스토어에 전달
        this.props.store.dispatch(add());
    }
}

export default StrAddButton;

 

src ➡️ action ➡️ index.js (src 폴더에 있는 action 폴더의 index.js)

컴포넌트에서 dispatch가 실행되면, 리듀서 함수는 액션 값을 참조해 작업을 실행합니다.

export const ADD = 'ADD';
export const add = () => {
    return {
        type: ADD
    }
}

 

src ➡️ reducers ➡️ index.js (src 폴더에 있는 reducers 폴더의 index.js)

combineReducers 함수는 여러 함수가 있다면, 하나의 리듀싱 함수로 변환시키고 src의 index.js에서 사용한 createStore 함수의 파라미터로 넘겨집니다. 스토어 state 값에 변경이 발생했기 때문에 subscribe 함수가 동작해 화면이 다시 렌더링 됩니다.

import {ADD} from '../actions'
import {combineReducers} from 'redux';

// 리듀서 데이터의 초깃값을 선언, 할당
const initState = {
    str: 100
}

// action.type이 ADD인 경우 state변수 str에 100을 추가
const data = (state = initState, action) => {
    switch (action.type) {
        case ADD:
            return state, {
                str: state.str + 100
            };
        default:
            return state;
    }
}

// 리듀서를 스토어에 남겨주기 위한 함수 combineReducers
const App = combineReducers({
    data
})

export default App;

 

실행 결과