Axios 是一个强大的 HTTP 客户端,允许您在 JavaScript 应用程序中轻松实现 Ajax 请求,我们已经涵盖了使用 Axios 的基本知识,所以您可以首先阅读 Axios 或 Axios + React 对您来说都是新的。
在本教程中,我们将使用Axios构建一个React应用程序内部的实时搜索功能,我们的应用程序将允许我们使用来自 themoviedb.org的API进行简单的电影搜索。
本教程分为3个部分:
- Part 1: 如何在 React 中使用 Axios 进行实时搜索
- Part 2: 防止不必要的请求
- Part 3: 缓存 HTTP 请求和响应
初始化 app
本教程假设您有使用 React 的经验,所以我们将跳过初始化步骤来节省我们宝贵的时间. 您可以使用您最喜欢的锅炉板,在本教程中我们将简单地使用 Create React App来初始化应用程序。
一旦应用程序初始化,让我们添加axios
:
1$ yarn add axios or npm i axios
接下来,将下面的代码复制到您的应用程序
组件:
1import React, { Component } from 'react';
2import axios from 'axios';
3
4import Movies from './Movies';
5
6class App extends Component {
7 state = {
8 movies: null,
9 loading: false,
10 value: ''
11 };
12
13 search = async val => {
14 this.setState({ loading: true });
15 const res = await axios(
16 `https://api.themoviedb.org/3/search/movie?query=${val}&api_key=dbc0a6d62448554c27b6167ef7dabb1b`
17 );
18 const movies = await res.data.results;
19
20 this.setState({ movies, loading: false });
21 };
22
23 onChangeHandler = async e => {
24 this.search(e.target.value);
25 this.setState({ value: e.target.value });
26 };
27
28 get renderMovies() {
29 let movies = <h1>There's no movies</h1>;
30 if (this.state.movies) {
31 movies = <Movies list={this.state.movies} />;
32 }
33
34 return movies;
35 }
36
37 render() {
38 return (
39 <div>
40 <input
41 value={this.state.value}
42 onChange={e => this.onChangeHandler(e)}
43 placeholder="Type something to search"
44 />
45 {this.renderMovies}
46 </div>
47 );
48 }
49}
50
51export default App;
注意:‘电影’只是演示 / 愚蠢的组件,它只是渲染我们给它的数据。
输入组件
因此,我们有一个受控的输入
元素,当我们输入时将onChangeHandler
方法称为onChangeHandler
。
搜索
從上面拿下列代碼:
1search = async val => {
2 this.setState({ loading: true });
3 const res = await axios(
4 `https://api.themoviedb.org/3/search/movie?query=${val}&api_key=dbc0a6d62448554c27b6167ef7dabb1b`
5 );
6 const movies = await res.data.results;
7
8 this.setState({ movies, loading: false });
9};
在搜索
方法中,我们正在向我们的API发出一个GET
请求,以获取我们想要的电影。一旦我们得到结果,我们通过setState
更新了组件的状态
。
这么简单!
避免不必要的请求
您可能会注意到,我们每次更新输入时都会发送请求,这可能会导致请求过载,特别是当我们收到大量响应时。
要查看此问题,请在浏览器的 DevTools 中打开网络选项卡,清除网络选项卡,在输入中输入一部电影的名称。
正如你所看到的,我们每一次键入时都会下载所有数据. 为了解决这个问题,让我们在src
目录中创建一个utils.js
文件:
1$ cd src
2$ touch utils.js
将以下代码复制到 utils.js
:
1import axios from 'axios';
2
3const makeRequestCreator = () => {
4 let token;
5
6 return (query) => {
7 // Check if we made a request
8 if(token){
9 // Cancel the previous request before making a new request
10 token.cancel()
11 }
12 // Create a new CancelToken
13 token = axios.CancelToken.source()
14 try{
15 const res = await axios(query, {cancelToken: cancel.token})
16 const result = data.data
17 return result;
18 } catch(error) {
19 if(axios.isCancel(error)) {
20 // Handle if request was cancelled
21 console.log('Request canceled', error.message);
22 } else {
23 // Handle usual errors
24 console.log('Something went wrong: ', error.message)
25 }
26 }
27 }
28}
29
30export const search = makeRequestCreator()
也可以更改应用
组件以利用我们的新实用功能:
1// ...
2import { search } from './utils'
3
4class App extends Component {
5 // ...
6
7 search = async val => {
8 this.setState({ loading: true });
9 // const res = await axios(
10 const res = await search(
11 `https://api.themoviedb.org/3/search/movie?query=${val}&api_key=dbc0a6d62448554c27b6167ef7dabb1b`
12 );
13 const movies = res;
14
15 this.setState({ movies, loading: false });
16 };
17 // ...
现在在那里发生了什么?
Axios
被称为取消令牌
(LINK0
)使我们能够取消请求。
在makeRequestCreator
中,我们创建了一个名为token
的变量,然后在一个请求中,如果存在token
的变量,我们将其称为cancel
的方法,以取消以前的请求,然后我们将token
分配给一个新的CancelToken
。
如果有什么不对劲,我们会捕捉到捕获
块中的错误,我们可以检查并处理请求是否被取消。
现在让我们看看网络标签中发生了什么:
正如你所看到的,我们只下载了一个答案. 现在 我们的用户只支付他们使用的东西。
HTTP 请求和响应
如果我们在输入中多次输入相同的文本,我们每次都会提出新的请求。
我们会改变我们的实用程序函数在utils.js
一点点:
1const resources = {};
2
3const makeRequestCreator = () => {
4 let cancel;
5
6 return async query => {
7 if (cancel) {
8 // Cancel the previous request before making a new request
9 cancel.cancel();
10 }
11 // Create a new CancelToken
12 cancel = axios.CancelToken.source();
13 try {
14 if (resources[query]) {
15 // Return result if it exists
16 return resources[query];
17 }
18 const res = await axios(query, { cancelToken: cancel.token });
19
20 const result = res.data.results;
21 // Store response
22 resources[query] = result;
23
24 return result;
25 } catch (error) {
26 if (axios.isCancel(error)) {
27 // Handle if request was cancelled
28 console.log('Request canceled', error.message);
29 } else {
30 // Handle usual errors
31 console.log('Something went wrong: ', error.message);
32 }
33 }
34 };
35};
36
37export const search = makeRequestCreator()
在这里,我们创建了一个资源
常数,它保留了我们下载的答案。当我们提出一个新的请求时,我们首先检查我们的资源
对象是否有这个请求的结果。
让我们用几句话概括一切。 每当我们在输入
中输入某些东西时:
- 我们取消以前的请求,如果有 *如果我们已经有以前的结果,我们只会返回它而不做一个新的请求 *如果我们没有这个结果,我们会创建一个新的结果,并存储它
如果您感兴趣,您可以在 This repo找到该应用程序的Redux版本。
结论
Congrats 🎉🎉🎉! We've built a live search feature which doesn't download unnecessary responses as well as caches responses. I hope you've learned a thing or two about how to build an efficient live search feature in React with the help of Axios.
现在,我们的用户花费尽可能少的流量数据. 如果你喜欢这个教程,请分享它! 😄
您可以找到本文的最终结果和源代码在 This CodeSandbox中。