연결을 사용하여 데이터 로드 및 표시
34040 단어 reacttypescriptjavascript
연결을 사용하여 데이터 로드
만약 우리가 Commodore 64개의 게임을 포함하는 REST API를 가지고 있다고 가정하자.그러니까 왜 안 해요?
요구사항: 목록을 불러오고 게임을 표시해야 합니다.
1. 기본값
다음은 서버에서 게임 목록을 검색하는 방법입니다.
const getGames = () => {
return fetch('http://localhost:3001/games/').then(response => response.json());
};
React 응용 프로그램에서 사용할 수 있습니다.우리의 첫 번째 교체는 다음과 같다.응용 프로그램.tsx(인덱스tsx로 표시)(see repo)
import React from 'react';
const getGames = () => {
return fetch('http://localhost:3001/games/').then(response => response.json());
};
export const App = () => {
const [games, setGames] = React.useState([]);
React.useEffect(() => {
getGames().then(games => setGames(games));
}, []);
return <pre>{JSON.stringify(games, null, 2)}</pre>;
};
App
구성 요소의 첫 번째 렌더링에서 games
수조는 비어 있습니다.그리고 getGames
의 약속이 해결될 때 games
수조는 우리의 모든 게임을 포함하고 매우 기본적인 방식으로 표시할 것이다.2. 맞춤형 반응 갈고리
단독 파일의 사용자 정의 React 갈고리로 쉽게 추출할 수 있습니다.
게임을 사용하다.ts(see repo)
import React from 'react';
const getGames = () => {
return fetch('http://localhost:3001/games/').then(response => response.json());
};
export const useGames = () => {
const [games, setGames] = React.useState([]);
React.useEffect(() => {
getGames().then(games => setGames(games));
}, []);
return games;
};
응용 프로그램.tsx(see repo)import React from 'react';
import { useGames } from './useGames';
export const App = () => {
const games = useGames();
return <pre>{JSON.stringify(games, null, 2)}</pre>;
};
3. 처리 오류 및 일시 중지 상태
우리의 사용자 정의 갈고리는 걸기와 오류 상태를 처리하지 않습니다.서버에서 데이터를 불러올 때 시각적 피드백이 없고, 더 나쁜 것은 데이터가 실패했을 때 오류 메시지가 없다는 것이다.서버가 닫히면 게임 목록이 비어 오류가 발생하지 않습니다.
우리는 이 문제를 해결할 수 있다.이런 도서관이 있는데 가장 인기 있는 것은 react-async이다.하지만 나는 아직 의존항을 추가하고 싶지 않다.오류 처리와 정지 상태에 필요한 최소 코드가 얼마나 되는지 봅시다.
UseAncync 함수
우리는 비동기 함수 (반환 약속) 와 기본값을 받아들이는 사용자 정의 갈고리를 만들었다.
이 갈고리는 세 개의 원소를 포함하는 원조인
[value, error, isPending]
을 되돌려줍니다.비동기 함수를 한 번 * 호출하고 오류가 발생하지 않는 한 해석할 때 값을 업데이트합니다.function useAsyncFunction<T>(asyncFunction: () => Promise<T>, defaultValue: T) {
const [state, setState] = React.useState({
value: defaultValue,
error: null,
isPending: true
});
React.useEffect(() => {
asyncFunction()
.then(value => setState({ value, error: null, isPending: false }))
.catch(error => setState({ ...state, error: error.toString(), isPending: false }));
}, [asyncFunction]); // *
const { value, error, isPending } = state;
return [value, error, isPending];
}
*useEffect
의 useAsyncFunction
은 비동기 함수를 한 번 호출하고 asyncFunction
이 변경될 때마다 호출합니다.추가 정보: Using the State Hook, Using the Effect Hook, Hooks API Reference.현재 게임을 사용하고 있습니다.우리는 이 새로운 사용자 정의 갈고리를 간단하게 사용하여
getGames
함수와 공수조의 초기 값을 매개 변수로 전달할 수 있다....
export const useGames = () => {
const games = useAsyncFunction(getGames, []); // 🤔 new array on every render?
return games;
};
그런데 작은 문제가 하나 있어요.useGames
을 호출할 때마다 우리는 새로운 공수 그룹을 전달합니다. 즉, App
구성 요소가 렌더링될 때입니다.그러면 렌더링할 때마다 데이터가 다시 추출되지만 추출할 때마다 새로운 렌더링이 발생하여 무한 순환이 발생합니다.초기 값을 갈고리 외부의 상수에 저장하여 이러한 상황을 피할 수 있습니다.
...
const emptyList = [];
export const useGames = () => {
const [games] = useAsyncFunction(getGames, emptyList);
return games;
};
에피소드
순수 JavaScript를 사용하는 경우 이 섹션을 건너뛸 수 있습니다.
엄격한 유형의 스크립트를 사용하는 경우 "noImplicitAny"컴파일러 옵션으로 인해 상기 코드가 작동하지 않습니다.이것은
const emptyList = [];
이 은식적으로 any
의 수조이기 때문이다.우리는 그것을
const emptyList: any[] = [];
으로 주석한 후에 계속할 수 있다.하지만 우리가 TypeScript를 사용하는 데는 이유가 있습니다.명확한 any
은 더욱 구체적일 수 있다.이 목록의 요소는 무엇입니까?게임!이것은 게임 목록이다.
const emptyList: Game[] = [];
물론 현재 우리는 Game
유형을 정의해야 한다.하지만 절망하지 마라!각 게임 객체는 다음과 같이 서버에서 JSON 응답을 받았습니다.{
"id": 5,
"title": "Kung-Fu Master",
"year": 1984,
"genre": "beat'em up",
"url": "https://en.wikipedia.org/wiki/Kung-Fu_Master_(video_game)",
"status": "in-progress",
"img": "http://localhost:3001/img/kung-fu-master.gif"
}
transform.tools을 사용하여 TypeScript 인터페이스(또는 유형)로 변환할 수 있습니다.type Game = {
id: number;
title: string;
year: number;
genre: string;
url: string;
status: 'not-started' | 'in-progress' | 'finished';
img: string;
};
그리고 하나 더:
useAsyncFunction
이 원조로 돌아왔다고 했지만 TypeScript의 추리(@3.6.2)는 이 점을 이해하지 못했다.반환 유형은 Array<(boolean | Game[] | null)>
으로 추정됩니다.우리는 함수의 반환 유형을 [T, string | null, boolean]
으로 현저하게 설명할 수 있다. 그 중에서 T
은 value
의 유형이고 (string | null)
은 error
의 유형이며 boolean
은 isPending
의 유형이다.export function useAsyncFunction<T>(
asyncFunction: () => Promise<T>,
defaultValue: T
): [T, string | null, boolean] {
...
}
이제 이 함수를 사용할 때 TypeScript는 올바른 유형을 제안합니다.const [games] = useAsyncFunction(getGames, emptyList); // games is of type Game[]
타자기 에피소드가 끝나다.맞춤형 연결 구성
비동기 함수를 사용합니다.ts는 지금 이렇게 보입니다. (see repo)
import React from 'react';
export function useAsyncFunction<T>(
asyncFunction: () => Promise<T>,
defaultValue: T
): [T, string | null, boolean] {
const [state, setState] = React.useState({
value: defaultValue,
error: null,
isPending: true
});
React.useEffect(() => {
asyncFunction()
.then(value => setState({ value, error: null, isPending: false }))
.catch(error =>
setState({ value: defaultValue, error: error.toString(), isPending: false })
);
}, [asyncFunction, defaultValue]);
const { value, error, isPending } = state;
return [value, error, isPending];
}
우리는 useGames
갈고리 중에서 그것을 사용한다.게임을 사용하다.ts(see repo)
import { useAsyncFunction } from './useAsyncFunction';
const getGames = (): Promise<Game[]> => {
return fetch('http://localhost:3001/games/').then(response => response.json());
};
type Game = {
id: number;
title: string;
year: number;
genre: string;
url: string;
status: 'not-started' | 'in-progress' | 'finished';
img: string;
};
const emptyList: Game[] = [];
export const useGames = () => {
const [games] = useAsyncFunction(getGames, emptyList);
return games;
};
오류 및 일시 중지 상태를 표시하려면 UI 변경
너무 좋아요.그러나 우리는 여전히 오류와 정지 상태를 처리하지 않았다.
App
구성 요소를 변경해야 합니다.import React from 'react';
import { useGames } from './useGames';
export const App = () => {
const { games, error, isPending } = useGames();
return (
<>
{error && <pre>ERROR! {error}...</pre>}
{isPending && <pre>LOADING...</pre>}
<pre>{JSON.stringify(games, null, 2)}</pre>
</>
);
};
우리의 useGames
갈고리는 세 개의 키가 있는 대상을 되돌려야 한다. games
, error
, isPending
이다.export const useGames = () => {
const [games, error, isPending] = useAsyncFunction(getGames, emptyList);
return { games, error, isPending };
};
또한 200과 다른 HTTP 상태 코드를 오류로 처리하는 getGames
함수를 개선했습니다.const getGames = (): Promise<Game[]> => {
return fetch('http://localhost:3001/games/').then(response => {
if (response.status !== 200) {
throw new Error(`${response.status} ${response.statusText}`);
}
return response.json();
});
};
지금까지 우리의 코드는 다음과 같다. (see repo)결론
RESTAPI에서 React 갈고리를 사용하여 데이터를 로드하는 방법에 대해 알아봤습니다.
에서 HTTP
PATCH
을 사용하여 원격 데이터 변경을 요청하는 방법과 요청이 성공했을 때 클라이언트 데이터를 업데이트하는 방법을 볼 수 있습니다.리소스
추가 읽기:
Reference
이 문제에 관하여(연결을 사용하여 데이터 로드 및 표시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/juliang/loading-and-displaying-data-with-hooks-jlj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)