如何在 React 中创建搜索栏 让我们来编写代码

2025-06-05

如何在 React 中创建搜索栏

让我们开始编码

我目前感兴趣的事情之一是创建一个搜索栏,但我不想搜索前端已有的内容。就像我不想通过点击按钮来向 API 发出请求一样。

我只是想使用一个输入,一旦我写完,我就会自动向 Api 发出请求,这就是今天的例子的挑战所在。

今天的例子的想法是写出《权力的游戏》中一个家族的名字,然后我们将列出这个家族的名字及其成员。

让我们开始编码

在今天的示例中,我们只需安装 axios 即可为我们的应用程序发出 http 请求:

npm i axios
Enter fullscreen mode Exit fullscreen mode

应用程序脚手架由您决定,因为无论您使用还是其他,它都可以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",
});
Enter fullscreen mode Exit fullscreen mode

然后我们就可以开始编写自定义钩子了。为了实现这一点,我们将使用两个你可能很熟悉的钩子:useState()useEffect()。就像我们要导入 axios 实例一样。

// @src/hooks/useFetch.js

import { useState, useEffect } from "react";

import got from "../api/got";

const useFetch = () => {
  // ...
  return;
};

export default useFetch;
Enter fullscreen mode Exit fullscreen mode

让我们首先创建状态,在本例中,它将是一个具有两个属性的对象。第一个属性slug是搜索词,也就是房屋名称。第二个属性是resultsApi 的响应。

// @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;
Enter fullscreen mode Exit fullscreen mode

现在我们可以使用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;
Enter fullscreen mode Exit fullscreen mode

但是,正如你可能已经想到的。如果我们现在在里面发出 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;
Enter fullscreen mode Exit fullscreen mode

现在我们可以使用 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;
Enter fullscreen mode Exit fullscreen mode

现在只需返回我们的状态和我们的设置器即可使用我们的自定义钩子。

// @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;
Enter fullscreen mode Exit fullscreen mode

现在我们可以开始创建 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>
  );
}
Enter fullscreen mode Exit fullscreen mode

现在我们可以开始创建我们的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>
  );
}
Enter fullscreen mode Exit fullscreen mode

最后,我们可以创建最后一个组件来列出每个家庭成员。

// @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>
  );
}
Enter fullscreen mode Exit fullscreen mode

您应该得到类似这样的结果:

最终应用程序

结论

一如既往,希望你觉得这篇文章有趣。如果你发现本文有任何错误,请在评论区指出。🪗

祝你度过美好的一天!👋 😜

文章来源:https://dev.to/franciscomendes10866/how-to-create-a-search-bar-in-react-58nj
PREV
如何使用 TypeORM 种子数据库让我们开始编码
NEXT
使用 Docker 部署的 Next.js 应用程序 - 有意义吗?