본문 바로가기

Front-End/React

React #22 (api 통신 - fetch, promise)

반응형

pp.325 ~ pp.333 

 

(아래 레포지토리에서 ch04_4 에 해당 하는 내용.)

https://github.com/yisj777s/doit-react-webapp-typescript

 

GitHub - yisj777s/doit-react-webapp-typescript: Do it! 리액트 개발자라면 이렇게 해야 인정받는다! 리액트로

Do it! 리액트 개발자라면 이렇게 해야 인정받는다! 리액트로 웹앱 만들기 with 타입스크립트 - GitHub - yisj777s/doit-react-webapp-typescript: Do it! 리액트 개발자라면 이렇게 해야 인정받는다! 리액트로 웹

github.com

 

※ 자세한 내용은 Backend 쪽에서 ...

 

 

fetch는 네트워크 요청을 위한 Web API, promise는 비동기 작업에 대해 완료 또는 실패를 반환

 

 

예시

fetch("htttps://randomuser.me/api/')		// api URL
	.then(res => res.json())		// res: response; json파일로 받아옴
    .then((data: unknown) => {			// data를 받아와서 results에 넣음
		const { results } = data as { results: IRandomUser[] }
		const user = convertRandomUser(result[0])

 

 

실습 - 버튼을 누르면 랜덤으로 유저 프로필 카드를 받아오는 기능

더보기

src/data/fetchRandomUser.ts

import { resolve } from "path";

export type IRandomUser = {
    email: string
    name: { title: string; first: string; last: string }
    picture: { large: string }
}


const convertRandomUser = (result: unknown) => {
    const { email, name, picture } = result as IRandomUser
    return { email, name, picture }
}


export const fetchRandomUser = (): Promise<IRandomUser> => 
    new Promise((resolve, reject) => {
        fetch('https://randomuser.me/api/')
        .then(res => res.json())
        .then((data: unknown) => {
            console.log(data)
            const { results } = data as { results: IRandomUser[] }
            resolve(convertRandomUser(results[0]));
        })
        .catch(reject)
    })

 

src/data/index.ts

export * from './util'
export * from './image'
export * from './chance'
export * from './date'
export * from './User'
export * from './Card'
export * from './fetchRandomUser'

 

src/pages/FetchTest.tsx

import { useState, useCallback, useEffect } from "react";
import { useToggle } from "../hooks";
import { Title, Avatar, Icon } from "../components";
import { Button } from "../theme/daisyui";
import * as D from '../data'


export default function FetchTest() {
    const [loading, toggleLoading] = useToggle()
    const [randomUser, setRandomUser] = useState<D.IRandomUser | null>(null)
    const [error, setError] = useState<Error | null>(null)

    const getRandomUser = useCallback(() => {
        toggleLoading()
        D.fetchRandomUser().then(setRandomUser).catch(setError).finally(toggleLoading)
    }, [toggleLoading])
    useEffect(getRandomUser, [getRandomUser])

    return (
        <section className="mt-4">
            <Title>FetchTest</Title>
            <div className="flex justify-center mt-4">
                <Button className="btn-sm btn-primary" onClick={getRandomUser}>
                    <Icon name="get_app"/>
                    <span>get random user</span>
                </Button>
            </div>
            
            {loading && (
                <div className="flex items-center justify-center">
                    <Button className="btn-circle loading"></Button>
                </div>
            )}

            {error && (
                <div className="p-4 mt-4 bg-red-200">
                    <p className="text-3xl text-red-500 text-bold">{error.message}</p>
                </div>
            )}

            {randomUser && (
                <div className="flex justify-center p-4 mt-4">
                    <Avatar src={randomUser.picture.large} />
                    <div className="ml-4">
                        <p className="text-xl text-bold">
                            {randomUser.name.title} {randomUser.name.first} {randomUser.name.last}
                        </p>
                        <p className="italic text-gray-600">{randomUser?.email}</p>
                    </div>
                </div>
            )}
        </section>
    )

}

 

src/App.tsx

import FetchTest from "./pages/FetchTest"

export default function App() {
  return (
    <main>
      <FetchTest />
    </main>
  )
}

 

 

 

실습했던 코드는 아래에서 확인 가능.

https://codesandbox.io/p/sandbox/fetch-promise-practice-forked-nqwtjk

 

 

 

 

 

 

 

 

 

 

반응형