React 是两个著眼的模块库。因而,它对怎样允诺远距统计数据没甚么提议。假如要透过 HTTP 允诺统计数据并将其发送至 Web API,能考量下面三种形式。
H55N读法INS13ZD自订 Hookreact-query/swr
特别注意:在责任编辑中,我将采用 fetch 展开 HTTP 初始化,但那些商业模式也适用于于 Axios 等等的代替形式。除此之外,假如你采用的是 GraphQ L,还能考量采用 Apollo 等等的其它极好的优先选择。这首诗假定你已经开始初始化现代的 REST API。
形式1:H55N
这是最单纯,最间接的优先选择。在 React 模块中展开 HTTP 初始化并处置积极响应。
fetch(“/users”).then(response => response.json());
看上去很单纯。但那个实例忽视了读取状况,consequences,新闻稿和增设有关状况等。在现实生活当今世界中, HTTP 初始化看上去更像这种。
import React,{ useState, useEffect } from”react”;exportdefaultfunctionInlineDemo(){const [users, setUsers]= useState([]);const [loading, setLoading]= useState(true);const [error, setError]= useState(null); useEffect(()=>{ fetch(${process.env.REACTAPPAPIBASEURL}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[].username;}
对两个单纯的插件,如果发动两个允诺,就能恒定组织工作。但下面的状况新闻稿和 useEffect 都是模板。假如我要展开很多 HTTP 初始化,我不该为每一初始化多次重复和保护约20行标识符。H55N初始化让你的标识符显得不雅观。
看呵呵他们要化解的许多难题:
新闻稿读取状况新闻稿错误状况将错误打印到控制台检查积极响应是否透过返回200 response.ok假如积极响应恒定,将积极响应转换为 json 并返回 promise假如积极响应不正确,抛出错误在 finally 中隐藏读取状况,以确保 Loading 即使发生错误也被隐藏新闻稿两个空的依赖项数组,以便 useEffect 只运行一次
这只是两个单纯的实例,它忽视了很多其它有关难题。
形式2:文件夹INS13ZD
假如他们在两个文件夹中处置所有 HTTP 初始化会怎么样?采用这种形式,他们创建了两个名为 services 的文件夹,并且把展开 HTTP 初始化的函数都放进去。service 是最流行的术语,我在下面也讨论了很多好的代替名称,如 client 或 api。
要点是,所有的 HTTP 初始化都是透过纯 JavaScript 函数处置的,存储在两个文件夹中。这是两个集中的 getUsers 函数:
exportfunctiongetUsers(){return fetch(${process.env.REACTAPPAPIBASEURL}users).then(response => response.json());}
下面是对 getUsers 函数的初始化:
import React,{ useState, useEffect } from”react”;import { getUsers } from”./services/userService”;exportdefaultfunctionCentralDemo(){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[].username;}
然而这并没太简化允诺初始化。主要的好处是它能强制一致地处置 HTTP 初始化。其思想是这种的:当有关函数一起处置时,更容易一致地处置它们。假如 userService 文件夹中充满了展开 HTTP 初始化的函数,那么我能很容易地确保它们始终如一地这种做。此外,假如初始化被复用,则很容易从那个集中位置初始化它们。
然而,他们还能做得更好。
形式3:自订Hook
借助 React Hooks 的魔力,他们终于能集中处置多次重复的逻辑。那么怎样创建两个自订 useFetch 钩子来简化他们的 HTTP 初始化呢?
import { useState, useEffect, useRef } from”react”;// This custom hook centralizes and streamlines handling of HTTP callsexportdefaultfunctionuseFetch(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.REACTAPPAPIBASEURL + 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 需要多少标识符:
import React from”react”;import useFetch from”./useFetch”;exportdefaultfunctionHookDemo(){const { data, loading, error }= useFetch(“users”);if (loading) return”Loading…”;if (error) return”Oops!”;return data[].username;}
对很多插件,你只需要两个这种的自订Hook。但那个Hook已经很复杂了,并且它消除了很多难题。
?怎样消除多次重复查询?
你能不断完善那个自订Hook来完成所有那些操作。但,您应该只需要形式4:
形式4:react-query/swr
采用 react-query或swr,能为他们处置缓存、重试、多次重复查询等等。我不必保护自己的自订Hook了。而且每一 HTTP 初始化都需要很少的标识符:
import React from”react”;import { getUsers } from”./services/userService”;import { useQuery } from”react-query”;exportdefaultfunctionReactQueryDemo(){const { data, isLoading, error }= useQuery(“users”, getUsers);if (isLoading) return”Loading…”;if (error) return”Oops!”;return data[].username;}
对大多数插件来说,今天这是我的首选。这是完整的标识符:https://codesandbox.io/s/4-ways-to-handle-restful-http-in-react-k3xug,你能自己展开比较。
你是怎么处置 HTTP 初始化的呢?欢迎和我讨论~