차근차근 생활 & 코딩

[REACT] 리액트 리덕스(react-redux) - Counter App 만들기 본문

IT/REACT(리액트)

[REACT] 리액트 리덕스(react-redux) - Counter App 만들기

ssilook 2021. 7. 30. 23:47
반응형

 

 

Step 1. npm install

   첫 번째로는 리액트를 설치하시면 됩니다. 설치 방법은 간단합니다.

   이미 설치 되어 있으신 분들 께서는 Step 2 넘어 가시면 됩니다.

 

[REACT] 리엑트 설치하기

리엑트 설치 및 실행 방법에 대해 간략히 설명 드리겠습니다. Part 1: React 설치 npm install -g create-react-app *기기에 Node >= 6 이상이 필요합니다. Part 2: React App 생성 create-react-app my-app Part..

ssilook.tistory.com

 

Step 2. npm install package

 Npm(create-react-app)이 실행 중이면 가장 먼저 할 일은 패키지를 설치하는 것입니다.

 다음 명령어를 입력해 5가지 라이브러리를 설치합니다.

$ npm install --save redux react-redux redux-devtools-extension redux-thunk redux-logger
  • redux : 자바스크립트 앱을 위한 예측 가능한 state 컨테이너
  • react-redux: 리덕스와 리엑트를 연동하기 위해서 필요한 라이브러리
  • redux-devtools-extension : 리덕스를 활용한 코드와 리덕스 크롬 확장 도구를 연동할 수 있도록 리덕스 개발자 확장 라이브러리
  • redux-thunk: 리덕스를 사용하는 어플리케이션에서 비동기 작업을 처리 할 때 사용하는 미들웨어
  • redux-logger: 이번에는 Redux의 store가 바뀔 때마다 콘솔 로깅해주는 미들웨어

 

Step 3. 리덕스 크롬 확장 도구 설치하기

 리덕스 디버깅을 도와줄 리덕스 크롬 확장 도구를 설치하겠습니다.
 링크를 클릭하여 Redux DevTools 확장 도구를 설치합니다.

 크롬 확장 도구 사용 방법에 대해서는 나중에 추가 설명드리도록 하겠습니다.

 

 

Redux DevTools

Redux DevTools for debugging application's state changes.

chrome.google.com

 

Step 4. "src" 디렉토리에 하위 디렉토리 폴더 생성

  src 디렉토리 폴더에 5개의 하위 폴더도 같이 생성해 줍니다.

디렉토리 구조

  • actions: 액션 유형 및 액션 생성자 파일을 저장합니다.
  • components: 구성 요소 보기에 해당하는 프레젠테이션 구성 요소를 저장합니다.
  • containers: 컨테이너 구성 요소 저장 저장소의 상태를 소품으로 가져옵니다.
  • reducers : 저장소의 기본 상태 값과 상태 업데이트를 담당하는 감속기 파일을 저장합니다.
  • utils: 일부 구성 요소가 함께 사용하는 파일을 저장합니다.

 

Step 5. 액션 함수정의 하기 / Create Actions

 액션 타입에 따라 액션 생성함수를 만들어주겠습니다.

 

src/actions/ActionTypes.js

export const INCREMENT = "INCREMENT";
export const DECREMENT = "DECREMENT";
export const SET_COLOR = "SET_COLOR";

 

src/actions/index.js

import * as types from "./ActionTypes";
export const increment = () => ({
	type: types.INCREMENT,
});
export const decrement = () => ({
	type: types.DECREMENT,
});
export const setColor = (color) => ({
	type: types.SET_COLOR,
color,
});

 

Step 6.  Create Reducer

여기에는 Reducer 상태를 변경하는 방법을 관리하는 정보가 포함되어 있습니다. Store와 정보를 교환하는 역할을 합니다.

 

1) 초기 상태와 리듀서 정의

 초기 상태와 리듀서를 정의해 줍니다.

 

src/reducers/countReducer.jsx

// Define the initial state
const initialState = {
    color: 'black',
    number: 0
};

function counter(state = initialState, action) {
    const { type, payload } = action;
    switch (type) {
        case 'INCREMENT': 
            return {
                ...state,
                number: state.number + 1
            };
        case 'DECREMENT':
            return {
                ...state,
                number: state.number - 1
            };
        case 'SET_COLOR':
            return {
                ...state,
                color: action.color
            };
        default:
            return state;
    }
};

export default counter;

 

2) comvineReducers로 Reducer 결합

  "combineReducers"는 많은 Reducer를 하나로 결합하여 Reducer로 관리할 수 있게 해줍니다. 

 

src/reducers/index.js

import { combineReducers } from 'redux';
import numbercount from './countReducer';

export default combineReducers({
    numbercount
});

 

 

Step 7. Create components

 

src/components/CounterFunction.js

import React from "react";
import PropTypes from "prop-types";
import "./Counter.css";
import { useSelector } from "react-redux";

const Counter = ({ onIncrement, onDecrement, onSetColor }) => {
    const number = useSelector((state) => state.numbercount.number);
    const color = useSelector((state) => state.numbercount.color);

    return (
        <div>
            <div
                className="Counter"
                onClick={onIncrement}
                onContextMenu={(e) => {
                    e.preventDefault();
                    onDecrement();
                }}
                onDoubleClick={onSetColor}
                style={{ backgroundColor: color }}
            >
                {number}
            </div>
        </div>
    );
};

Counter.propTypes = {
    number: PropTypes.number,
    color: PropTypes.string,
    onIncrement: PropTypes.func,
    onDecrement: PropTypes.func,
    onSetColor: PropTypes.func,
};

Counter.defaultProps = {
    number: 0,
    color: "black",
    onIncrement: () => console.warn("onIncrement not defined"),
    onDecrement: () => console.warn("onDecrement not defined"),
    onSetColor: () => console.warn("onSetColor not defined"),
};

export default Counter;

 

src/components/Counter.css

.Counter {
    /* layout */
    width: 10rem;
    height: 10rem;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 1rem;

     /* color */
    color: white;

    /* font */
    font-size: 3rem;

    /* etc */
    border-radius: 100%;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.75s;
}

 

Step 8. Create containers

 

 mapStateToProps

   : state를 파라미터로 받아 컴포넌트의 props로 사용할 객체를 반환합니다.

 mapDispatchToProps

   : dispatch를 파라미터로 받아 action을 dispatch하는 함수들을 객체 안에 넣어서 반환합니다.

 

src/containers/CouterContainer.js

import Counter from "../components/CounterFunction";
import * as actions from "../actions";
import { connect } from "react-redux";
import { getRandomColor } from "../utils";

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

const mapDispatchToProps = (dispatch) => ({
    onIncrement: () => dispatch(actions.increment()),
    onDecrement: () => dispatch(actions.decrement()),
    onSetColor: () => {
        const color = getRandomColor();
        dispatch(actions.setColor(color));
    },
});

const CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter);

export default CounterContainer;

 

Step 9. Create utils

 카운터 클릭 시 색상이 랜덤으로 변경되도록 합니다.

 

src/utils/index.js

export function getRandomColor() {
    const colors = [
        '#495057',
        '#f03e3e',
        '#d6336c',
        '#ae3ec9',
        '#7048e8',
        '#4263eb',
        '#1c7cd6',
        '#1098ad',
        '#0ca678',
        '#37b24d',
        '#74b816',
        '#f59f00',
        '#f76707'
    ];

    // 0 부터 12까지 랜덤 숫자
    const random = Math.floor(Math.random() * 13);

    // 랜덤 색상 반환
    return colors[random];
}

 

Step 10. Provider component Setting

 Redux와 같은 라이브러리는 루트 구성 요소에서 전체 React 구성 요소에 액세스할 수 있는 저장소 데이터를 생성해야 합니다.

  • Store : Store는 앱의 전체 상태를 저장하는 창고.
  • CreateStore : 리듀서, 스토어 데이터의 초기값, 미들웨어 함수를 인자로 받음.

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import { createStore, applyMiddleware } from "redux"; //Add
import { Provider } from "react-redux"; //Add
import { composeWithDevTools } from 'redux-devtools-extension'; //리덕스 크롬 개발자도구 사용하기 위한 라이브러리
import reducers from './reducers'; //Add
import thunk from "redux-thunk";

//스토어(createStore)를 만들고 리덕스 크롬 개발자도구(composeWithDevTools) 사용
const store = createStore(reducers, composeWithDevTools(applyMiddleware(thunk)));

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

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

src/App.js

import logo from './logo.svg';
import './App.css';
import CounterContainer from './containers/CouterContainer';

function App() {
  return (
    <div className="App">
      <CounterContainer />
    </div>
  );
}

export default App;

 

 크롬에서 F12를 누구게 되면 오른쪽 화면에 Redux로 변경하게 되면 아래와 같은 화면이 나옵니다.

 * 단 리액트 화면에서만 Redux라는 것이 활성화되니 다른 화면에서는 표시 안되어 주의 하시면 됩니다.

리덕스를 정리하면서 정말 어려웠던것 같습니다.

 

리엑트를 하시는 분들은 꼭 필수로, 어렵더라도 익히시길 바래요.

 

처음에는 왜 이걸 해야되는지 이해되지 않지만 작업을 하면 할수록 필요하단걸 느끼실 겁니다. 

 

수고하셨습니다.

반응형
Comments