React REST API 使用入门指南
介绍
React 是一个流行的前端框架,开发者用它来创建应用程序。如果你想构建实际应用,迟早都需要将 API 集成到你的 React 应用中。每个想要使用 React 构建现代化、实际 Web 应用的开发者都必须了解如何使用 API 将数据导入到 React 应用中。
在本入门指南中,我们将学习如何在 React 中使用 RESTful API,包括获取、删除和添加数据。我们还将介绍使用 RESTful API 的两种主要方式,以及如何将它们与 React Hooks 结合使用。
什么是 REST API?
如果你曾经花时间编程或研究编程,那么你几乎肯定遇到过“API”这个术语。API 代表应用程序编程接口,它是一种允许不同应用程序以编程方式相互通信并实时返回响应的媒介。
Roy Fielding 于 2000 年将 REST 定义为一种架构风格和方法论,常用于互联网服务(例如分布式超媒体系统)的开发。它是“表述性状态转移”(REpresentational State Transfer)的缩写。
当通过 REST API 发出请求时,它会将资源当前状态的表示形式发送给请求者或端点。这种状态表示形式可以采用 JSON(JavaScript 对象表示法)、XML 或 HTML 格式。JSON 是使用最广泛的文件格式,因为它与编程语言无关,并且可以被人和机器读取。
例如:
[
{
"userId": 1,
"id": 1,
"title": "sunt excepturi",
"body": "quia et suscipit\nsuscipit recusandae consequuntur "
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil"
}
]
在 React 中使用 REST API
在 React 应用程序中使用 REST API 可以通过多种方式实现,但在本指南中,我们将介绍两种最流行的方法:Axios(基于 Promise 的 HTTP 客户端)和 Fetch API(浏览器内置的 Web API)。
注意:要完全理解本指南,您应该熟悉 JavaScript、React 和 React hooks,因为它们是本指南的核心。
在深入探讨如何使用 API 之前,需要了解的是,在 React 中使用 API 的方式与在 JavaScript 中使用 API 的方式截然不同,因为这些请求现在是在 React 组件中执行的。在我们的例子中,我们将使用函数式组件,这就需要用到两个主要的 React Hooks:
- useEffect Hook:在 React 中,我们会在 hook 中执行 API 请求,
useEffect()以便在应用挂载时立即渲染,或者在应用达到特定状态后渲染。以下是常用的语法:
useEffect(() => {
// data fetching here
}, []);
- useState Hook:当我们请求数据时,必须准备一个状态来存储返回的数据。我们可以将其保存在 Redux 等状态管理工具或 context 对象中。为了简化操作,我们将返回的数据存储在 React 本地状态中。
const [posts, setPosts] = useState([]);
现在让我们进入本指南的核心部分,学习如何使用JSONPlaceholder 帖子 API获取、添加和删除数据。由于本指南面向初学者,因此这些知识也适用于任何类型的 API。
使用 Fetch API 调用 API
Fetch API 是 JavaScript 内置的从服务器或 API 端点检索资源的方法。它是内置的,不需要安装任何依赖项或软件包。
该fetch()方法需要一个必需参数,即要获取的资源的路径或 URL,然后返回一个 Promise,以便您可以使用 ` then()and`catch()方法处理成功或失败。
一个基本的 fetch 请求编写起来非常简单,如下所示:我们只是从一个返回 JSON 格式数据的 URL 获取数据,然后将其记录到控制台:
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
.then(response => response.json())
.then(data => console.log(data));
注意:默认响应通常是常规的 HTTP 响应,而不是实际的 JSON,但我们可以使用响应的 json() 方法将输出获取为 JSON 对象。
在 React 中使用 Fetch API 执行 GET 请求
HTTP GET 方法可用于从端点请求数据;如前所述,Fetch API 接受一个必需参数,即 true;它还接受一个可选参数,尤其是在使用默认的 GET 方法时;但是,对于其他方法(例如 POST 和 DELETE),必须将方法附加到选项数组中:
fetch(url, {
method: "GET" // default, so we can ignore
})
到目前为止,我们已经了解了它的工作原理,现在让我们把所学知识融会贯通,并执行一个 GET 请求来从我们的 API 获取数据。如前所述,我们将使用免费的在线 API JSONPlaceholder将帖子列表获取到我们的应用程序中:
import React, { useState, useEffect } from 'react';
const App = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
.then((response) => response.json())
.then((data) => {
console.log(data);
setPosts(data);
})
.catch((err) => {
console.log(err.message);
});
}, []);
return (
// ... consume here
);
};
我们在前面的代码中创建了一个状态来存储我们将从 API 获取的数据,以便我们稍后可以在应用程序中使用它,我们还将默认值设置为空数组。
const [posts, setPosts] = useState([]);
主要操作随后在 useEffect 状态下进行,以便在应用程序加载后立即获取数据/帖子。获取请求会返回一个 Promise,我们可以接受或拒绝它:
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10').then(
(response) => console.log(response)
);
}, []);
此响应包含大量数据,例如状态码、文本以及其他后续处理错误所需的信息。目前,我们使用 `resolve` 处理了 `resolve` 操作.then(),但它返回的是一个响应对象,这不是我们想要的,因此我们需要使用 `resolve` 方法将响应对象解析为 JSON 格式json(),该方法还会返回一个 Promise,以便我们使用第二个 `resolve` 方法获取实际数据.then()。
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
.then((response) => response.json())
.then((data) => {
console.log(data);
setPosts(data);
});
}, []);
查看控制台,我们可以看到已经从 API 获取了 10 个帖子,并且已将它们的状态设置为之前指定的状态。但这并不完整,因为我们只处理了 Promise 的 resolve,而没有处理 Promise 的 reject,后者需要使用以下.catch()方法处理:
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
.then((response) => response.json())
.then((data) => {
console.log(data);
setPosts(data);
})
.catch((err) => {
console.log(err.message);
});
}, []);
到目前为止,我们已经了解了如何执行GET请求,可以通过遍历数组轻松地将其集成到我们的应用程序中:
const App = () => {
// ...
return (
<div className="posts-container">
{posts.map((post) => {
return (
<div className="post-card" key={post.id}>
<h2 className="post-title">{post.title}</h2>
<p className="post-body">{post.body}</p>
<div className="button">
<div className="delete-btn">Delete</div>
</div>
</div>
);
})}
</div>
);
};
export default App;
在 React 中使用 Fetch API 执行 POST 请求
HTTPPOST方法可用于从端点发送数据;它的工作方式与GET请求类似,主要区别在于必须将方法和两个附加参数添加到可选对象中:
const addPosts = async (title, body) => {
await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
title: title,
body: body,
userId: Math.random().toString(36).slice(2),
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.json())
.then((data) => {
setPosts((posts) => [data, ...posts]);
setTitle('');
setBody('');
})
.catch((err) => {
console.log(err.message);
});
};
看起来比较特殊的参数是请求体和请求头。请求体包含我们要传递给 API 的数据,由于要将数据发送到 Web 服务器,因此必须先将其字符串化。请求头则指定数据类型,在使用 REST API 时,数据类型始终相同。我们还会设置状态来保存新数据,并将剩余数据分发到数组中。
查看addPost()我们创建的方法,它需要从表单或其他来源获取这些数据;在本例中,我创建了一个表单,通过状态获取了表单数据,然后在表单提交时将其添加到该方法中:
import React, { useState, useEffect } from 'react';
const App = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
// ...
const addPosts = async (title, body) => {
await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
title: title,
body: body,
userId: Math.random().toString(36).slice(2),
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.json())
.then((data) => {
setPosts((posts) => [data, ...posts]);
setTitle('');
setBody('');
})
.catch((err) => {
console.log(err.message);
});
};
const handleSubmit = (e) => {
e.preventDefault();
addPosts(title, body);
};
return (
<div className="app">
<div className="add-post-container">
<form onSubmit={handleSubmit}>
<input type="text" className="form-control" value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<textarea name="" className="form-control" id="" cols="10" rows="8"
value={body} onChange={(e) => setBody(e.target.value)}
></textarea>
<button type="submit">Add Post</button>
</form>
</div>
{/* ... */}
</div>
);
};
export default App;
使用 Fetch API 在 React 中执行 DELETE 请求
HTTPDELETE方法可用于从端点删除数据;它的工作方式与GET请求类似,主要区别在于添加了方法:
const deletePost = async (id) => {
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: 'DELETE',
}).then((response) => {
if (response.status === 200) {
setPosts(
posts.filter((post) => {
return post.id !== id;
})
);
} else {
return;
}
});
};
当按钮被点击时,此操作会被触发。我们会获取id点击按钮的具体帖子,然后从返回的所有数据中移除该帖子的数据。这些数据会从 API 中移除,但不会立即从用户界面中移除,因此我们添加了一个过滤器来同时移除这些数据。对于循环中的每个项目,删除按钮将显示如下:
const App = () => {
// ...
return (
<div className="posts-container">
{posts.map((post) => {
return (
<div className="post-card" key={post.id}>
{/* ... */}
<div className="button">
<div className="delete-btn" onClick={() => deletePost(post.id)}>
Delete
</div>
</div>
</div>
);
})}
</div>
);
};
export default App;
在 Fetch API 中使用 Async/await
到目前为止,我们已经了解了如何使用 Promise 语法正常发起 fetch 请求,但由于 `.then` 的存在,这种语法有时会让人感到困惑。接下来是链式调用。我们可以通过使用 Async/await 来避免使用 `.then` 链式调用,从而编写更易读的代码。
要使用 async/await,首先async在函数中调用它,然后在发出请求并期望得到响应时,await在函数前面添加语法,等待直到 promise 得到结果。
当我们使用 async/await 时,所有 Fetch 请求都会像这样:
import React, { useState, useEffect } from 'react';
const App = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [posts, setPosts] = useState([]);
// GET with fetch API
useEffect(() => {
const fetchPost = async () => {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts?_limit=10'
);
const data = await response.json();
console.log(data);
setPosts(data);
};
fetchPost();
}, []);
// Delete with fetchAPI
const deletePost = async (id) => {
let response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`,
{
method: 'DELETE',
}
);
if (response.status === 200) {
setPosts(
posts.filter((post) => {
return post.id !== id;
})
);
} else {
return;
}
};
// Post with fetchAPI
const addPosts = async (title, body) => {
let response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
title: title,
body: body,
userId: Math.random().toString(36).slice(2),
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
});
let data = await response.json();
setPosts((posts) => [data, ...posts]);
setTitle('');
setBody('');
};
const handleSubmit = (e) => {
e.preventDefault();
addPosts(title, body);
};
return (
// ...
);
};
export default App;
错误处理
在本节中,我们将探讨如何以传统方式以及使用 async/await 来处理错误。我们可以使用响应数据来处理 Fetch API 中的错误,也可以在使用 async/await 时使用 try/catch 语句。让我们先来看看在 Fetch API 中如何以常规方式处理错误:
const fetchPost = () => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then((data) => {
console.log(data);
setPosts(data);
})
.catch((err) => {
console.log(err.message);
});
};
您可以点击此处阅读更多关于Fetch API错误的信息。
对于 async/await,我们可以try像catch这样使用:
const fetchPost = async () => {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts?_limit=10'
);
const data = await response.json();
setPosts(data);
} catch (error) {
console.log(error);
}
};
使用 Axios 调用 API
Axios 是一个基于 Promise 的 HTTP 客户端库,它可以轻松地向 REST 端点发送异步 HTTP 请求。在本例中,该端点是 JSONPlaceholder Posts API,我们将向其发送 `<post>` GET、POST`<post>` 和DELETE`<post>` 请求。
安装和配置 Axios 实例
与 Fetch API 不同,Axios 不是内置的,因此我们需要将其集成到项目中才能使用它。我们可以通过运行以下命令将 Axios 添加到项目中:
npm install axios
安装成功后,我们可以创建实例。创建实例是可选的,但建议这样做,因为它可以避免不必要的重复操作。要创建实例,我们使用以下.create()方法:该方法可以指定 URL 和可能的标头等信息:
import axios from "axios";
const client = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/posts"
});
在 React 中使用 Axios 执行 GET 请求
我们将使用之前声明的实例,只需设置参数(如有),并默认以 JSON 格式获取响应。与 Fetch API 方法不同,声明此方法无需任何选项;我们只需将方法附加到实例并进行查询即可。
useEffect(() => {
client.get('?_limit=10').then((response) => {
setPosts(response.data);
});
}, []);
在 React 中使用 Axios 执行 POST 请求
如前所述,该POST方法可用于向端点发送数据;它的功能与GET请求类似,主要区别在于需要包含该方法以及用于保存我们要发送的数据的选项:
const addPosts = (title, body) => {
client
.post('', {
title: title,
body: body,
})
.then((response) => {
setPosts((posts) => [response.data, ...posts]);
});
};
使用 Axios 在 React 中执行 DELETE 请求
我们可以使用 delete 方法执行删除请求,该方法会获取数据id并将其从 API 中删除;我们还可以使用 filter 方法将其从 UI 中移除,就像我们使用 Fetch API 方法所做的那样:
const deletePost = (id) => {
client.delete(`${id}`);
setPosts(
posts.filter((post) => {
return post.id !== id;
})
);
};
在 Axios 中使用 Async/Await
到目前为止,我们已经了解了如何使用 promise 语法发出 Axios 请求,但现在让我们看看如何使用 async/await 来编写更少的代码并避免.then()链式调用。
当我们使用 async/await 时,所有 Axios 请求都将如下所示:
import React, { useState, useEffect } from 'react';
const App = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [posts, setPosts] = useState([]);
// GET with Axios
useEffect(() => {
const fetchPost = async () => {
let response = await client.get('?_limit=10');
setPosts(response.data);
};
fetchPost();
}, []);
// Delete with Axios
const deletePost = async (id) => {
await client.delete(`${id}`);
setPosts(
posts.filter((post) => {
return post.id !== id;
})
);
};
// Post with Axios
const addPosts = async (title, body) => {
let response = await client.post('', {
title: title,
body: body,
});
setPosts((posts) => [response.data, ...posts]);
};
const handleSubmit = (e) => {
e.preventDefault();
addPosts(title, body);
};
return (
// ...
);
};
export default App;
错误处理
对于基于 Promise 的 axios 请求,我们可以使用 ` .then()and`catch (方法,但对于 async/await,我们可以使用try...catch代码块。这与 Fetch API 的实现方式非常相似,try...catch代码块如下所示:
const fetchPost = async () => {
try {
let response = await client.get('?_limit=10');
setPosts(response.data);
} catch (error) {
console.log(error);
}
};
您可以点击此处阅读更多关于使用 Axios 处理错误的信息。
Fetch API 与 Axios 对比
您可能已经注意到一些差异,但我们也希望您能注意到这些差异。这些区别将帮助您决定针对特定项目使用哪种方法。这些区别包括:
| Axios | 拿来 |
|---|---|
| Axios 是一个独立的第三方软件包,安装起来非常简单。 | Fetch 功能已内置于大多数现代浏览器中;无需进行任何安装。 |
| Axios 使用了data属性。 | 获取数据时会用到body属性。 |
| Axios 数据包含对象。 | Fetch 的身体必须被字符串化。 |
| 当状态码为 200 且状态文本为“OK”时,Axios 请求被接受。 | 当响应对象包含 ok 属性时,获取请求有效。 |
| Axios 可自动转换 JSON 数据。 | 处理 JSON 数据时,获取数据是一个两步过程——首先,发出实际请求;其次,对响应调用 .json() 方法。 |
| Axios允许取消请求和请求超时。 | 获取功能不会。 |
| Axios内置了下载进度显示功能。 | 获取功能不支持上传进度。 |
| Axios 对多种浏览器都有支持。 | 当状态码为 200 且状态文本为“OK”时,Axios 请求被接受。Fetch 仅兼容 Chrome 42+、Firefox 39+、Edge 14+ 和 Safari 10.1+。(这称为向后兼容性)。 |
结论
在本指南中,我们学习了如何在 React 中使用 Fetch API 或 Axios 来调用 REST API。这将帮助您入门 React 中的 API 调用,并在此基础上,您将能够执行更多独特的数据调用和 API 操作。
文章来源:https://dev.to/olawanle_joel/beginners-guide-to-consuming-rest-apis-in-react-2blg