본문 바로가기

React

React Native / 서버요청 커스텀 훅 만들기

스프링교재에서 실습한 코드를 기반으로 서버를 작성하였다.

 

스프링서버에서 응답하는 객체 형태

 

 

컨트롤러를 확인해보면 /api/articles로 요청하면 Article객체가 요소인 리스트 형태로 응답을 받을 수 있다.

 

Article 엔티티의 구조를 보면

id, title, content속성이 있다.

 

postman을 사용하여 스프링 서버로 요청하여 객체 형태 확인하기

 

출력을 확인한 결과 id, title, content필드가 있는 요소들의 배열로 응답을 받는 것을 확인할 수 있었다.

 

리액트 네이티브에서 관련타입 정의하고 요청 로직 작성하기

 

import { useEffect, useState } from 'react';
import ArticleView from '../src/components/ArticleView';
import axios from 'axios';
import { View } from 'react-native';
import styled from '@emotion/native';

interface article {
  id: number;
  title: string;
  content?: string;
}

export default function ArticlePage(): JSX.Element {
  const [article, setArticle] = useState<Array<article> | null>();
  const [loading, setLoading] = useState<boolean>(false);
  const [ok, setOk] = useState<boolean>(false);
  useEffect(() => {
    setLoading(true);
    (async function fetchArticles() {
      try {
        const response = await axios('내아이피는공개하지않아/api/articles');
        console.log(response.data);
        setArticle(response.data);
        setOk(true);
      } catch (e) {
        console.log(e);
        setOk(false);
      }
    })();
    setLoading(false);
  }, []);

  return (
    <Container>
      {article &&
        ok &&
        article.map((article) => (
          <ArticleView key={article.id} article={article} loading={loading} />
        ))}
    </Container>
  );
}

const Container = styled.View`
  background-color: ${({ theme }) => theme.bg.basic};
  flex: 1;
  align-items: flex-start;
  justify-content: center;
  padding: 16px;
`;

 

 

useEffect내부에서 스프링서버로 비동기요청을 하는 코드이다.

 

출력

 

비동기 요청 코드 다시 작성하기

 

useArticle 커스텀 훅 작성하기

import React from 'react';

function useArticle<T>(
  url: string,
  { method, body }: { method: string; body?: XMLHttpRequestBodyInit }
) {
  const [result, setResult] = React.useState<T | undefined>();
  const [isLoading, setIsLoading] = React.useState(false);
  const [ok, setOk] = React.useState<boolean | undefined>();
  const [status, setStatus] = React.useState<number | undefined>();

  React.useEffect(() => {
    const abortController = new AbortController();

    (async () => {
      setIsLoading(true);

      const response = await fetch(url, {
        method,
        body,
        signal: abortController.signal,
      });

      setOk(response.ok);
      setStatus(response.status);

      if (response.ok) {
        const apiResult = await response.json();
        setResult(apiResult);
      }

      setIsLoading(false);
    })();
  }, [url, method, body]);

  return { result, isLoading, ok, status };
}

export default useArticle;

 

useArticle 커스텀 훅은 비동기 요청의 완료 여부, 결과, 상태, 로딩여부를 반환하는 훅이다.

 

Article컴포넌트에서 useArticle 커스텀 훅 사용하기

 

import { useEffect, useState } from 'react';
import ArticleView from '../src/components/ArticleView';
import axios from 'axios';
import { View } from 'react-native';
import styled from '@emotion/native';
import { Typography } from 'dooboo-ui';
import useArticle from '../src/hooks/useArticle';

interface article {
  id: number;
  title: string;
  content?: string;
}

export default function ArticlePage(): JSX.Element {
  const {
    result: article,
    isLoading,
    ok,
  } = useArticle<article[]>('아이피 공개 못하지렁/api/articles', {
    method: 'GET',
  });

  if (isLoading) {
    return (
      <View>
        <Typography.Body1>Loading...</Typography.Body1>
      </View>
    );
  }

  return (
    <Container>
      {article &&
        ok &&
        article.map((article) => (
          <ArticleView key={article.id} article={article} />
        ))}
    </Container>
  );
}

const Container = styled.View`
  background-color: ${({ theme }) => theme.bg.basic};
  flex: 1;
  align-items: flex-start;
  justify-content: center;
  padding: 16px;
`;

 

 

출력

정리

이전까지 비동기요청을 수행한다고 하면 리덕스와 리덕스 사가 미들웨어를 이용하여 코드의 길이와 초기 투자 비용이 컸다.

모던 리액트에서 언급한 useEffect 사용에 대한 부분을 기초로 하여 간단한 API요청의 경우 useEffect를 사용한 커스텀 훅을 제작하여 코드의 길이를 간소화하고 전역상태를 사용하지 않고도 구현할 수 있었다.

 

관련 글:

https://dongubak.tistory.com/44