본문 바로가기
Books/러닝 리액트 ✔️

[Learning React] 8장 - 데이터 포함시키기

by Aaron-Kim 2022. 2. 1.

8.1 데이터 요청하기

  - 요청으로 데이터 보내기

  - fetch로 파일 업로드하기

    - multipart-formatdata 라는 다른 HTTP 요청을 보내야 함

      - 서버에게 request body에 하나 이상의 파일이 들어가 있다고 알려줌

  - 권한 요청

    - 보통 사용자는 자신을 식별하도록 서비스가 부여한 유일한 토큰을 요청마다 덧붙여서 자신의 신원 표현

    - 토큰은 Authorization 헤더에 추가됨

  - 데이터를 로컬 스토리지에 저장하기

    - window.localStorage

      - 데이터를 제거하기 전까지 무기한 보관

    - window.sessionStorage

      - 데이터를 사용자 세션에만 저장

      - 탭을 닫거나 브라우저를 재시작하면 데이터 사라짐

  - 프라미스 상태 처리하기

    - 프라미스 3가지 상태

      - pending (진행 중)

      - fulfilled/resolved (성공, 처리 완료)

      - rejected (실패, 거부)

    - 모든 request에서 3가지 처리 꼭 필요

      - 모든 HTTP request를 재사용 가능한 훅이나 컴포넌트로 처리하거나,

        리액트 기능인 Suspense로 처리 가능

8.2 렌더 프롭

  - render prop: 렌더링되는 프로퍼티 (프로퍼티로 전달되는 컴포넌트)

    - 특정 조건을 만족할 때 렌더링 되는 컴포넌트 => render prop

    - 비동기 컴포넌트의 재사용성을 극대화하고 싶을 때 유용

8.3 가상화된 리스트

  - react-window 모듈의 FixedSizeList 컴포넌트

  - fetch 훅 만들기

    - 커스텀 훅; fetch 요청을 보낼 때 필요한 로직 재사용 가능

 

// useFetch 훅

import React, { useState, useEffect } from 'react';

export default function useFetch(uri) {
  const [data, setData] = useState();
  const [error, setError] = useState();
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!uri) return;
    fetch(uri)
      .then((data) => data.json())
      .then(setData)
      .then(() => setLoading(false))
      .catch(setError);
  }, [uri]);

  return {
    loading,
    data,
    error,
  };
}

 

  - fetch 컴포넌트 만들기

 

import React, { useState } from 'react';
import useFetch from './hooks/useFetch';

function Fetch({
  uri,
  loadingFallback = <p>Loading...</p>,
  renderError = (error) => <pre>{JSON.stringify(error, null, 2)}</pre>,
  renderSuccess,
}) {
  const { loading, data, error } = useFetch(uri);
  if (loading) return loadingFallback;
  if (error) return renderError(error);
  if (data) return renderSuccess({ data });
}

function GithubUser({ login }) {
  return (
    <Fetch
      uri={`https://api.github.com/users/${login}`}
      renderSuccess={UserDetails}
    />
  );
}

function UserDetails({ data }) {
  return (
    <div className="githubUser">
      <img src={data.avatar_url} alt={data.login} style={{ width: 200 }} />
      <div>
        <h1>{data.login}</h1>
        {data.name && <p>{data.name}</p>}
        {data.location && <p>{data.location}</p>}
      </div>
    </div>
  );
}

function App() {
  const [login, setLogin] = useState('moontahoe');

  return (
    <>
      <GithubUser login={login} />
    </>
  );
}

export default App;

 

  - 여러 요청 처리하기

 

// useIterator 훅

import React, { useState } from 'react';

export const useIterator = (items = [], initialIndex = 0) => {
  const [i, setIndex] = useState(initialIndex);

  const prev = () => {
    if (i === 0) return setIndex(items.length - 1);
    setIndex(i - 1);
  };

  const next = () => {
    if (i === items.length - 1) return setIndex(0);
    setIndex(i + 1);
  };

  return [items[i], prev, next];
};

 

  - 값 메모화하기

 

import React, { useState, useCallback, useMemo } from 'react';

export const useIterator = (items = [], initialIndex = 0) => {
  const [i, setIndex] = useState(initialIndex);

  const prev = useCallback(() => {
    if (i === 0) return setIndex(items.length - 1);
    setIndex(i - 1);
  }, [i]);

  const next = useCallback(() => {
    if (i === items.length - 1) return setIndex(0);
    setIndex(i + 1);
  }, [i]);

  const item = useMemo(() => items[i], [i]);

  return [item || items[0], prev, next];
};

 

  - 폭포수 요청

    - 각 요청은 이전 요청에 의존

  - 네트워크 속도 제한

  - 병렬 요청

  - 값 기다리기

  - 요청 취소하기

8.4 그래프QL 소개

  - 깃허브 그래프QL API

    - 리액트UI를 선언적으로 정의하는 해법

    - 그래프QLAPI와 통신하는 법을 선언적으로 정의하는 방법

  - 그래프QL 요청 보내기

    - 그래프QL 요청은 request body에 쿼리가 들어 있는 HTTP 요청


[Source Code] 러닝 리액트 Ch08. 데이터 포함시키기

반응형

댓글