项目 49(共 100 个)- 使用自动完成功能进行搜索

2025-05-25

项目 49(共 100 个)- 使用自动完成功能进行搜索

嘿!我的任务是截止 3 月 31 日,完成 100 个 React.js 项目。请关注我的 dev.to 个人资料或推特获取最新动态,如有任何问题,请随时联系我。感谢您的支持!

已部署项目的链接:链接
仓库链接:github

今天我想在 React 中创建一个自动完成组件,因为我之前从未在 React 中实现过搜索功能,更不用说自动完成功能了。我其实很好奇其他人是如何从零开始实现这个功能的,因为使用星球大战 API 来实现这个功能相当简单。他们有自己的搜索功能,返回一个 JSON 结果数组,而且任何搜索返回的星球大战角色数量必然很少。如果你的数据库有 10 万个可能的结果怎么办?我想大多数数据库的结果数量都可以设置一个数字限制。

对于基础搜索组件,我改编了这篇 Dev.to 博客文章,将其变成了一个功能组件。我没有使用他们的 API,而是决定使用一个开放的星球大战角色搜索 API,它不需要注册,也不需要暴露我的邮箱地址。

该网站的结构很简单。它使用一个App组件和一个Search组件,重要的逻辑都发生在这里。它使用了三个状态querysearchResults并且selectedCharacter它们在初始化时都设置为空:

  const [query,setQuery] = useState('');
  const [searchResults,setSearchResults] = useState([]);
  const [selectedCharacter,setSelectedCharacter] = useState(null);
Enter fullscreen mode Exit fullscreen mode

在返回语句中,我们为搜索功能创建一个带有文本输入的表单:

return (
    <form className='search-form-container'>
      <input 
        placeholder='Search for...'
        onChange={handleInputChange}
        value={query}
      />
    </form>
  )
Enter fullscreen mode Exit fullscreen mode

当用户搜索时,我们使用他们的搜索 URL 查询发起对星球大战 API 的 API 调用:

const searchURL = 'https://swapi.dev/api/people/?search=';

const getInfo = () => {
    console.log('Getting info from API...')
    fetch(searchURL+query)
      .then(res => res.json())
      .then(data => setSearchResults(data.results))
      .catch(e => {
        console.log({error: e});
    });
}

const handleInputChange = (e) => {
    setQuery(e.target.value)
    if (query && query.length > 0) {
      getInfo();
    }
}
Enter fullscreen mode Exit fullscreen mode

如果 API 返回结果,我们会将ul结果填充到搜索框下方的一个元素中。我通常使用标准的 map 方法,并key为返回的 JSX 子元素创建一个 prop,但我想用一种新的方式实现它——使用React.Children.toArray().map 方法。这样,您就不必自己创建 key prop 了。

const results = React.Children.toArray(
    searchResults.map((item,idx) => (
      <li className='result-item' id={idx} onClick={handleQueryResultClick}>{item.name}</li>
    ))
)
Enter fullscreen mode Exit fullscreen mode

看起来如下:

替代文本

如果用户选择其中一个li元素,则存储在原始结果数组中的该元素的索引searchResults将与该元素的 id 匹配li

const handleQueryResultClick = (e) => {
    const searchResultId = e.target.id;
    setSelectedCharacter(searchResults[searchResultId]);
    setQuery([]);
}
Enter fullscreen mode Exit fullscreen mode

然后,我们将该角色搜索到的数据填充到搜索框下方的 div 中,并清除查询状态以移除ul搜索结果元素。我使用了三元组来实现这一点。

<div>
        {selectedCharacter ? (
          <div className='character-display-container'>
            <p><span className='character-info-title'>name:</span> {selectedCharacter.name}</p>
            <p><span className='character-info-title'>height:</span> {selectedCharacter.height}</p>
            <p><span className='character-info-title'>mass:</span> {selectedCharacter.mass}</p>
          </div>
        ) : (
          <p className='no-results-prompt'>There are no results. Try typing something into the search bar above.</p>
        )}
</div>
Enter fullscreen mode Exit fullscreen mode

就是这样!比我想象的要简单,主要是因为 API 非常容易使用。我强烈建议你尝试一下。

文章来源:https://dev.to/jameshubert_com/project-49-of-100-search-with-autocomplete-5g5f
PREV
成为中级开发人员 开始前的一些注意事项 成为中级开发人员的首要指标 青春期对你的职业生涯有什么影响 一些特质 一些建议 不断学习! 有什么想法? 保持联系 规划你的软件开发职业生涯 时事通讯
NEXT
10 种 Python 编程优化技术。