Quatre façons de demander des données distantes : 1. Effectuer des appels HTTP directement dans le composant React et traiter la réponse ; 2. Créer un dossier, y mettre toutes les fonctions qui effectuent des appels HTTP, centraliser les données de la requête et traiter la réponse ; 3. Personnalisez Hook pour demander des données ; 4. Utilisez « react-query » ou swr pour demander des données.
L'environnement d'exploitation de ce tutoriel : système Windows 7, React version 17.0.1, ordinateur Dell G3.
React
est une bibliothèque de composants dédiée. Par conséquent, il propose peu de suggestions sur la manière de demander des données à distance. Si vous souhaitez demander des données via HTTP
et les envoyer à API Web
, voici quatre approches à considérer. React
是一个专注的组件库。因此,它对如何请求远程数据没有什么建议。如果要通过 HTTP
请求数据并将其发送到 Web API
,可以考虑下面四种方法。
内联写法
集中管理
自定义 Hook
react-query/swr
注意:在本文中,我将使用 fetch 进行 HTTP 调用,但是这些模式也适用于 Axios 之类的替代方法。另外,如果你使用的是 GraphQ L,还可以考虑使用 Apollo 之类的其他不错的选择。这篇文章假设你正在调用传统的 REST API。
这是最简单,最直接的选择。在 React
组件中进行 HTTP
调用并处理响应。
fetch("/users").then(response => response.json());
看起来很简单。但是这个示例忽略了加载状态,错误处理,声明和设置相关状态等。在现实世界中, HTTP
调用看起来更像这样。
import React, { useState, useEffect } from "react"; export default function InlineDemo() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(`${process.env.REACT_APP_API_BASE_URL}users`) .then(response => { if (response.ok) return response.json(); throw response; }) .then(json => { setUsers(json); }) .catch(err => { console.error(err); setError(err); }) .finally(() => { setLoading(false); }); }, []); if (loading) return "Loading..."; if (error) return "Oops!"; return users[0].username; }
对于一个简单的应用程序,只要发起几个请求,就可以正常工作。但是上面的状态声明和 useEffect
都是模版。如果我要进行许多 HTTP
调用,我不想为每个调用重复和维护大约 20 行代码。内联调用让你的代码变得很丑。
看一下我们要解决的一些问题:
声明加载状态
声明错误状态
将错误打印到控制台
检查响应是否通过返回 200 response.ok
如果响应正常,将响应转换为 json
并返回 promise
如果响应不正确,抛出错误
在 finally
中隐藏加载状态,以确保 Loading
即使发生错误也被隐藏
声明一个空的依赖项数组,以便 useEffect
只运行一次
这只是一个简单的示例,它忽略了许多其他相关问题。
如果我们在一个文件夹中处理所有 HTTP
调用会怎么样? 使用这种方法,我们创建了一个名为 services
的文件夹,并且把进行 HTTP 调用的函数都放进去。service
是最流行的术语,我在下面也讨论了很多好的替代名称,如 client
或 api
。
要点是,所有的 HTTP
调用都是通过纯 JavaScript
函数处理的,存储在一个文件夹中。这是一个集中的 getUsers
函数:
export function getUsers() { return fetch(`${process.env.REACT_APP_API_BASE_URL}users`).then(response => response.json() ); }
下面是对 getUsers
函数的调用:
import React, { useState, useEffect } from "react"; import { getUsers } from "./services/userService"; export default function CentralDemo() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { getUsers() .then(json => { setUsers(json); setLoading(false); }) .catch(err => { console.error(err); setError(err); }); }, []); if (loading) return "Loading..."; if (error) return "Oops!"; return users[0].username; }
然而这并没有太简化请求调用。主要的好处是它可以强制一致地处理 HTTP
调用。其思想是这样的:当相关函数一起处理时,更容易一致地处理它们。如果 userService
文件夹中充满了进行 HTTP
调用的函数,那么我可以很容易地确保它们始终如一地这样做。此外,如果调用被复用,则很容易从这个集中位置调用它们。
然而,我们还可以做得更好。
借助 React Hooks
的魔力,我们终于可以集中处理重复的逻辑。那么如何创建一个自定义 useFetch
钩子来简化我们的 HTTP
调用呢?
import { useState, useEffect, useRef } from "react"; // This custom hook centralizes and streamlines handling of HTTP calls export default function useFetch(url, init) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const prevInit = useRef(); const prevUrl = useRef(); useEffect(() => { // Only refetch if url or init params change. if (prevUrl.current === url && prevInit.current === init) return; prevUrl.current = url; prevInit.current = init; fetch(process.env.REACT_APP_API_BASE_URL + url, init) .then(response => { if (response.ok) return response.json(); setError(response); }) .then(data => setData(data)) .catch(err => { console.error(err); setError(err); }) .finally(() => setLoading(false)); }, [init, url]); return { data, loading, error }; }
你的可能看起来不一样,但我发现这个基本的使用方法很有用。这个 Hook 极大地简化了所有调用。看看使用这个 Hook
Hook
personnaliséreact-query/swr
🎜HTTP
et gérez la réponse dans le composant React
. 🎜import React from "react"; import useFetch from "./useFetch"; export default function HookDemo() { const { data, loading, error } = useFetch("users"); if (loading) return "Loading..."; if (error) return "Oops!"; return data[0].username; }
HTTP
ressemblerait davantage à ceci. 🎜import React from "react"; import { getUsers } from "./services/userService"; import { useQuery } from "react-query"; export default function ReactQueryDemo() { const { data, isLoading, error } = useQuery("users", getUsers); if (isLoading) return "Loading..."; if (error) return "Oops!"; return data[0].username; }
useEffect
sont tous deux des modèles. Si je dois passer de nombreux appels HTTP
, je ne veux pas répéter et conserver environ 20 lignes de code pour chaque appel. Les appels en ligne rendent votre code moche. 🎜🎜Examinez certains des problèmes que nous souhaitons résoudre : 🎜response.ok
🎜json< /code> et renvoyer <code>promesse
🎜enfin< /code> pour vous assurer que <code>Loading
est masqué même si des erreurs se produisent🎜useEffect
ne s'exécute qu'une seule fois🎜 li>< /ul>🎜🎜Ceci n'est qu'un exemple simple qui ignore de nombreux autres problèmes connexes. 🎜🎜🎜Méthode 2 : Gestion centralisée des dossiers🎜🎜Et si nous traitions tous les appels HTTP
dans un seul dossier ? En utilisant cette méthode, nous créons un fichier appelé dossier services< /code> et le plaçons toutes les fonctions qui y effectuent des appels HTTP. <code>service
est le terme le plus populaire, et j'ai également discuté de nombreux bons noms alternatifs ci-dessous, tels que client
ou api
. 🎜🎜🎜🎜Le point principal est que tous les HTTP</code > Les appels sont traités via des fonctions <code>JavaScript
pures, stockées dans un dossier. Il s'agit d'une fonction getUsers
centralisée : 🎜rrreee🎜 Voici l'appel à la fonction getUsers
: 🎜rrreee🎜 Cependant cela ne simplifie pas trop l'appel de requête. Le principal avantage est qu'il applique une gestion cohérente des appels HTTP
. L'idée est la suivante : lorsque les fonctions liées sont traitées ensemble, il est plus facile de les traiter de manière cohérente. Si le dossier userService
est rempli de fonctions qui effectuent des appels HTTP
, je peux facilement m'assurer qu'elles le font de manière cohérente. De plus, si les appels sont réutilisés, ils sont facilement invoqués depuis cet emplacement centralisé. 🎜🎜Cependant, nous pouvons faire mieux. 🎜🎜Méthode 3 : Custom Hook🎜🎜Avec la magie des React Hooks
, nous pouvons enfin nous concentrer sur le traitement de la logique répétitive. Alors, comment pouvons-nous créer un hook useFetch
personnalisé pour simplifier nos appels HTTP
? 🎜rrreee🎜Le vôtre peut paraître différent, mais je trouve cette méthode d'utilisation de base utile. Ce Hook simplifie grandement tous les appels. Regardez combien de code il faut pour utiliser ce Hook
:🎜rrreee🎜Pour de nombreuses applications, vous n'avez besoin que d'un seul Hook personnalisé comme celui-ci. Mais ce Hook est déjà complexe et élimine de nombreux problèmes. 🎜🎜Mais il reste encore de nombreux points que nous n'avons pas pris en compte : la mise en cache ? . Si la connexion du client n'est pas fiable, comment l'obtenir à nouveau ? Voulez-vous récupérer de nouvelles données lorsque l'utilisateur redimensionne l'étiquette ? Comment éliminer les requêtes en double ? 🎜🎜Vous pouvez continuer à améliorer ce Hook personnalisé pour réaliser toutes ces opérations. Cependant, vous ne devriez avoir besoin que de la méthode 4 :🎜使用 react-query或swr
,可以为我们处理缓存、重试、重复查询等等。我不必维护自己的自定义Hook了。而且每个 HTTP
调用都需要很少的代码:
import React from "react"; import { getUsers } from "./services/userService"; import { useQuery } from "react-query"; export default function ReactQueryDemo() { const { data, isLoading, error } = useQuery("users", getUsers); if (isLoading) return "Loading..."; if (error) return "Oops!"; return data[0].username; }
对于大多数应用程序来说,今天这是我的首选。这是完整的代码:https://codesandbox.io/s/4-ways-to-handle-restful-http-in-react-k3xug
,你可以自己进行比较。
推荐学习:《react视频教程》
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!