본문 바로가기

오픈소스/노드

[Node] React 정리(19) - Reducer를 이용하여 API 연동 기본

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

 

자바스크립트, 노드, 리액트들은 비동기 프로그래밍임을 알아야 합니다. 비동기 처리를 위해 Promise 와 Asnyc/await 를 사용하고 있으며, API 데이터를 가져오는 경우에도 비동기적으로 작동하기 때문에 이러한 로직처리를 하기 위해서는 그에 알맞는 함수와 사용법을 이미 알고 있어야 함을 알려드립니다. 본 예제에서는 useReducer와 axios 라이브러리를 이용하여 데이터를 비동기적으로 가져오는 방법에 대해 알아보도록 하겠습니다.

 

러면 useReducer 를 이용한 API 활용 에 대해 배워보도록 합시다.

 

완성된 예제는 다음 링크를 통해 미리 보실 수 있습니다.

https://github.com/libtv/React_Note/tree/master/19.%20api-integrate

 

 

# Contents


  • useReducer 를 이용한 API 활용

 

 

# useReducer 를 이용한 API 활용


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

 

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

 

npx create-creat-app api-integrate
cd api-integrate
npm install --save axios styled-components

 

우리가 이번에 API 연동 실습을 할 때에는 JSONPlaceholder 에 있는 연습용 API 를 사용해볼 것입니다.

https://jsonplaceholder.typicode.com/users 결과물은 다음과 같은 형식으로 이루어져있습니다.

 

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
        "lat": "-43.9509",
        "lng": "-34.4618"
      }
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net",
    "company": {
      "name": "Deckow-Crist",
      "catchPhrase": "Proactive didactic contingency",
      "bs": "synergize scalable supply-chains"
    }
  },
  (...)
]

 

페이지가 로딩 상태일 때에는 로딩중입니다 라는 메시지가 Body 태그에 나오게 되고, axios의 결과 값이 나오는 데로, data를 전송하는 예제를 작성해보았습니다.

 

아래 코드를 통해 App.js를 수정합니다.

 

import axios from "axios";
import React, { useCallback, useEffect, useReducer } from "react";
import styled, { css } from "styled-components";

const MyList = styled.h3`
    color: red;
    font-size: 15px;
`;

const initialState = {
    loading: true,
    data: null,
};

const MyButton = styled.button`
    font-size: 20px;
    background-color: aquamarine;
    ${(props) => {
        if (props.visible)
            return css`
                display: none;
            `;
    }}
`;

function reducer(state, action) {
    switch (action.type) {
        case "LOADING":
            return {
                ...state,
                loading: true,
            };

        case "RENDER":
            return {
                ...state,
                loading: false,
                data: action.data,
            };
    }
}

function App() {
    const [state, dispatch] = useReducer(reducer, initialState);
    const { loading, data } = state;

    useEffect(async () => {
        const response = await axios.get("https://jsonplaceholder.typicode.com/users");
        dispatch({
            type: "RENDER",
            data: response.data,
        });
    }, [loading]);

    const onClick = useCallback(() => {
        dispatch({
            type: "LOADING",
        });
    });

    return (
        <div className="App">
            <>
                {loading
                    ? "로딩중입니다."
                    : data.map((list) => {
                          return (
                              <MyList>
                                  {list.id} : {list.name} - {list.email}
                              </MyList>
                          );
                      })}
                <MyButton onClick={onClick} visible={loading}>
                    다시 불러오기
                </MyButton>
            </>
        </div>
    );
}

export default App;

 

이처럼 비동기적 API를 사용할 때에는 useEffect 에서 로딩한 데이터를 통해 렌더링 하는 것이 바람직하다고 생각합니다.

데이터가 변경될 때 리렌더링을 제공함으로써 좀 더 유연하고 동적인 페이지를 작성할 수 있습니다.