如何在 React 中创建搜索栏
让我们开始编码
我目前感兴趣的事情之一是创建一个搜索栏,但我不想搜索前端已有的内容。就像我不想通过点击按钮来向 API 发出请求一样。
我只是想使用一个输入,一旦我写完,我就会自动向 Api 发出请求,这就是今天的例子的挑战所在。
今天的例子的想法是写出《权力的游戏》中一个家族的名字,然后我们将列出这个家族的名字及其成员。
让我们开始编码
在今天的示例中,我们只需安装 axios 即可为我们的应用程序发出 http 请求:
npm i axios
应用程序脚手架由您决定,因为无论您使用还是其他,它都可以create-react-app
工作vite
。
首先,我们将创建 axios 实例,然后使用权力的游戏引语 API。
// @src/api/got.js
import axios from "axios";
export default axios.create({
baseURL: "https://game-of-thrones-quotes.herokuapp.com/v1/house",
});
然后我们就可以开始编写自定义钩子了。为了实现这一点,我们将使用两个你可能很熟悉的钩子:useState()
和useEffect()
。就像我们要导入 axios 实例一样。
// @src/hooks/useFetch.js
import { useState, useEffect } from "react";
import got from "../api/got";
const useFetch = () => {
// ...
return;
};
export default useFetch;
让我们首先创建状态,在本例中,它将是一个具有两个属性的对象。第一个属性slug
是搜索词,也就是房屋名称。第二个属性是results
Api 的响应。
// @src/hooks/useFetch.js
import { useState, useEffect } from "react";
import got from "../api/got";
const useFetch = () => {
const [data, setData] = useState({
slug: "",
results: [],
});
// ...
return;
};
export default useFetch;
现在我们可以使用useEffect()
,每当 slug 发生变化时,它都会被执行。像这样:
// @src/hooks/useFetch.js
import { useState, useEffect } from "react";
import got from "../api/got";
const useFetch = () => {
const [data, setData] = useState({
slug: "",
results: [],
});
useEffect(() => {
// ...
}, [data.slug]);
return;
};
export default useFetch;
但是,正如你可能已经想到的。如果我们现在在里面发出 http 请求useEffect()
,则意味着每当用户写入一个新字符时,他都会向 Api 发出新的请求。
但我们不希望这样,所以我们将使用setTimeout()
,因为我们希望用户完成写入后立即完成 http 请求,为此我们将设置一秒钟的超时时间。
但这样一来,我们就会冒风险,最终可能会出现多次超时,而我们不希望出现这种情况。这是因为,如果超时开始后,用户再次写入,我们希望取消之前的超时。因此,我们需要清理我们的useEffect()
,然后用它clearTimeout()
来取消之前的超时。就像这样:
// @src/hooks/useFetch.js
import { useState, useEffect } from "react";
import got from "../api/got";
const useFetch = () => {
const [data, setData] = useState({
slug: "",
results: [],
});
useEffect(() => {
if (data.slug !== "") {
const timeoutId = setTimeout(() => {
// ...
}, 1000);
return () => clearTimeout(timeoutId);
}
}, [data.slug]);
return;
};
export default useFetch;
现在我们可以使用 axios 实例发起 http 请求,并将我们的slug
作为唯一参数传递。然后,我们将响应数据存储在状态中。
// @src/hooks/useFetch.js
import { useState, useEffect } from "react";
import got from "../api/got";
const useFetch = () => {
const [data, setData] = useState({
slug: "",
results: [],
});
useEffect(() => {
if (data.slug !== "") {
const timeoutId = setTimeout(() => {
const fetch = async () => {
try {
const res = await got.get(`/${data.slug}`);
setData({ ...data, results: res.data });
} catch (err) {
console.error(err);
}
};
fetch();
}, 1000);
return () => clearTimeout(timeoutId);
}
}, [data.slug]);
return;
};
export default useFetch;
现在只需返回我们的状态和我们的设置器即可使用我们的自定义钩子。
// @src/hooks/useFetch.js
import { useState, useEffect } from "react";
import got from "../api/got";
const useFetch = () => {
const [data, setData] = useState({
slug: "",
results: [],
});
useEffect(() => {
if (data.slug !== "") {
const timeoutId = setTimeout(() => {
const fetch = async () => {
try {
const res = await got.get(`/${data.slug}`);
setData({ ...data, results: res.data });
} catch (err) {
console.error(err);
}
};
fetch();
}, 1000);
return () => clearTimeout(timeoutId);
}
}, [data.slug]);
return { data, setData };
};
export default useFetch;
现在我们可以开始创建 UI 了,首先从我们的开始App.jsx
。同样,我们将导入自定义钩子并导入House.jsx
组件(尚未创建),然后进行条件渲染,因为只有在有房屋数据的情况下才会显示。
// @src/App.jsx
import React from "react";
import useFetch from "./hooks/useFetch";
import House from "./components/House";
export default function App() {
const { data, setData } = useFetch();
return (
<main>
<input
type="text"
placeholder="Type your favorite house"
value={data.slug}
onChange={(e) => setData({ ...data, slug: e.target.value })}
/>
<br />
{data.results.length > 0 ? <House family={data.results[0]} /> : null}
</main>
);
}
现在我们可以开始创建我们的House.jsx
组件,并在其中导入Members.jsx
(尚未创建)。
// @src/components/House.jsx
import React from "react";
import Members from "./Members";
export default function House({ family }) {
return (
<div>
<h1>{family.name}</h1>
<Members members={family.members} />
</div>
);
}
最后,我们可以创建最后一个组件来列出每个家庭成员。
// @src/components/Members.jsx
import React from "react";
export default function Members({ members }) {
return (
<ul>
{members.map((el, i) => (
<li key={i}>{el.name}</li>
))}
</ul>
);
}
您应该得到类似这样的结果:

结论
一如既往,希望你觉得这篇文章有趣。如果你发现本文有任何错误,请在评论区指出。🪗
祝你度过美好的一天!👋 😜
文章来源:https://dev.to/franciscomendes10866/how-to-create-a-search-bar-in-react-58nj