본문 바로가기

오픈소스/노드

[Node] React 정리(23) - 리덕스 모듈화

리액트로 프로젝트를 생성하여 개발하는 과정 중 리액트의 필수 문법 및 기초적인 부분, 심화 과정 등을 정리한 문서입니다. 정리한 부분에는 제가 이해하는 관점에서만 정리를 하였기 때문에 초점은 보여주는 형식이 아닌 제가 필요할 때 사용하려는 목적이 담겨져 있습니다. 

 

리액트 프로젝트에 리덕스를 적용하기 위해서 리덕스 모듈을 만들어보도록 하겠습니다. 리덕스 모듈이란 다음 항목들이 모두 들어있는 자바스크립트 파일을 의미합니다. 우리는 리듀서와 액션 관련 코드들을 하나의 파일에 몰아서 작성해보도록 하겠습니다. 이를 Ducks 패턴이라고 부릅니다. 리덕스 관련 코드를 분리하는 방식은 정해져있는 방식이 없으므로 나중에는 여러분이 자유롭게 분리하셔도 상관없습니다.

 

완성된 코드는 아래 주소를 확인해주시기 바랍니다.

https://github.com/libtv/React_Note/tree/master/23.%20learn-redux-second

 

GitHub - libtv/React_Note: This is a notebook organized by React.

This is a notebook organized by React. Contribute to libtv/React_Note development by creating an account on GitHub.

github.com

 

 

# Contents


  • 리덕스 모듈화

 

 

# 리덕스 모듈화


새로운 프로젝트를 생성하고 라이브러리를 설치하겠습니다.

 

아래 명령어를 통해 프로젝트와 라이브러리를 설치합니다.

npx create-react-app learn-redux
cd learn-redux
npm install --save redux

 

리덕스를 구현하는 모듈 디렉토리는 modules 에 존재하도록 하겠습니다. 그리고 구현된 리덕스를 사용하는 모듈 디렉토리는 container로 묶어보도록 하겠습니다. 아래 예제는 간단한 TodoList의 예제입니다. 텍스트에 입력을 하고 버튼을 클릭하게 되면 입력된 인풋 값이 아래 리스트에 추가되는 코드로써 기본적인 예제이므로 간단하게 이해할 수 있습니다.

 

modules/todos.js 의 전체 코드입니다. 해당 파일을 생성한 후 작성하세요.

//* initialize Variable */
const initializeState = [];
let nextId = 0;

//* action type */
const ADD_LIST = "ADD_LIST";
const TOGGLE_LIST = "TOGGLE_LIST";

//* craete action *//
export function addList(text) {
    return {
        type: ADD_LIST,
        todo: {
            id: nextId++,
            text: text,
        },
    };
}

export function toggleList(id) {
    return {
        type: TOGGLE_LIST,
        id,
    };
}

//* create Reducer */
export default function todoReducer(state = initializeState, action) {
    switch (action.type) {
        case ADD_LIST:
            return state.concat(action.todo);
        case TOGGLE_LIST:
            return;
        default:
            return state;
    }
}

 

modules/rootReducer.js 의 전체 코드입니다. 해당 파일을 생성한 후 작성하세요.

import { combineReducers } from "redux";
import todoReducer from "./todos";

const rootReducer = combineReducers({ todoReducer });
export default rootReducer;

 

Context API에서 Provider를 제공했던 것처럼 redux 에서도 Provider를 제공하여 사용해야 합니다.

본 내용은 적용된 redux의 store를 Provider 하는 과정입니다. 아래 내용을 참고해주세요.

 

index.js 의 전체 코드입니다. 해당 파일을 작성하세요.

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import rootReducer from "./modules/rootReducer";
import { Provider } from "react-redux";
import { createStore } from "redux";

const store = createStore(rootReducer);

console.log(store.getState());

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <App />
        </Provider>
    </React.StrictMode>,
    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();

 

Provider로 제공한 store를 사용하는 방법에 대한 것 입니다.

컨테이너에서는 제공된 함수와 객체를 이용하여 데이터를 제공해주는 역할을 하고 있습니다.

 

container/TodoContainer.js 의 전체 코드입니다. 해당 파일을 생성한 후 작성하세요.

import { addList, toggleList } from "../modules/todos";
import { useSelector, useDispatch } from "react-redux";
import TodoList from "../components/TodoList";

function TodoContainer() {
    const { todos } = useSelector((state) => ({
        todos: state.todoReducer,
    }));

    const dispatch = useDispatch();

    const onClick = (text) => {
        dispatch(addList(text));
    };

    const onToggle = (id) => {
        dispatch(toggleList(id));
    };

    return (
        <>
            <TodoList todos={todos} onClick={onClick} onToggle={onToggle}></TodoList>
        </>
    );
}

export default TodoContainer;

 

받은 데이터들을 사용하는 컴포넌트입니다.

컴포넌트에서는 받은 데이터를 가공하여 사용자에게 직접 렌더링 해주는 역할을 하고 있습니다.

 

components/TodoList.js 의 전체 코드입니다. 해당 파일을 생성한 후 작성하세요.

import React, { useState } from "react";
import styled from "styled-components";
import TodoItem from "./TodoItem";

function TodoList({ children, todos, onClick, onToggle }) {
    const [state, dispatch] = useState("");

    const onChange = (e) => {
        e.preventDefault();
        var text = e.target.value;
        dispatch(text);
    };

    const onMyClick = () => {
        onClick(state);
    };

    return (
        <>
            <input onChange={onChange} value={state}></input>
            <button onClick={onMyClick}>클릭</button>
            {todos !== null
                ? todos.map((todo) => {
                      return <TodoItem id={todo.id} text={todo.text}></TodoItem>;
                  })
                : null}
        </>
    );
}

export default TodoList;

 

components/TodoItem.js 의 전체 코드입니다. 해당 파일을 생성한 후 작성하세요.

import React from "react";
import styled from "styled-components";

function TodoItem({ children, id, text }) {
    return (
        <>
            <div>
                <h2>{id}</h2> : <h3>{text}</h3>
            </div>
        </>
    );
}

export default TodoItem;

 

마지막으로 생성된 컨테이너를 App.js 에 렌더시켜 사용자에게 뷰를 제공해줍니다.

 

App.js 의 전체 코드입니다. 해당 파일을 작성하세요.

import logo from "./logo.svg";
import "./App.css";
import TodoContainer from "./container/TodoContainer";

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

export default App;