【问题标题】:Search component showing last result when input field is cleared using backspace使用退格键清除输入字段时显示最后结果的搜索组件
【发布时间】:2021-10-16 10:43:14
【问题描述】:

所以我使用 Next.js 并构建了一个基本搜索页面,其中包含输入并将查询后的结果存储在状态数组中。问题是当我使用退格快速清除输入字段时,它会显示最后一个关键字的结果。

我认为我以错误的方式使用了 React 状态。

这是我使用 meilisearch 查询搜索的方式:

const [search, setSearch] = useState([]);
const [showSearch, setShowSearch] = useState(false);

async function onChange(e) {
    if (e.length > 0) {

      await client.index('sections')
        .search(e)
        .then((res) => {
          const list = res.hits.map((elm) => ({
            title: elm.Title,
            content: elm.formattedContent
          }));

          setSearch(list);
          setShowSearch(true);
        });
    } else {
      setSearch([]);
      setShowSearch(false);
    }
  }

这是输入字段和搜索结果:

<div className="searchPage wrapper">
        <input
          type="text"
          aria-label="Search through site content"
          placeholder="Search your keywords"
          onChange={(e) => onChange(e.target.value);}
        />

        {showSearch && (
          <div className="searchPageResults">
            <p className="suggested">Top Results</p>
            {search.length > 0 ? (
              <ul>
                {search.map((item, index) => (
                  <li key={`search-${index}`}>
                    <Link href={`/${item.slug}`}>
                      <a role="link">
                        {item.title}
                      </a>
                    </Link>

                    <p>{item.content}</p>
                  </li>
                ))}
              </ul>
            ) : (
              <p className="noResults">No results found</p>
            )}
          </div>
        )}
      </div>

预防这种情况的最佳做法是什么?

您可以在此处查看实时实现:https://budgetbasics.openbudgetsindia.org/search

重现问题:

  • 搜索一些东西,例如:Budget
  • 显示结果后,按住退格键,当字段被清除时,搜索结果显示为b
  • 如果我选择字段中的所有文本并使用退格键将其删除,则问题不存在。

【问题讨论】:

    标签: reactjs search next.js meilisearch


    【解决方案1】:

    问题

    我怀疑当您快速退格时,使用“b”发出的最后一个请求异步解析之后最后一次onChange 调用是在e.length &gt; 0 为假的情况下进行的. search 状态更新为空数组,一旦最终异步请求解决,search 状态将更新为“b”的结果。

    解决方案

    一种可能的解决方案是消除onChange 处理程序的抖动,这样就不会为快速打字机发出无用的请求。来自 lodash 的 debounce 是一个常见的实用程序。我使用了300ms 的延迟,但这显然可以调整以满足您的需求以及对您或您的一般用户感觉最好的方式。

    import debounce from 'lodash/debounce';
    
    async function onChange(e) {
      if (e.length > 0) {
        await client.index('sections')
          .search(e)
          .then((res) => {
            const list = res.hits.map((elm) => ({
              title: elm.Title,
              content: elm.formattedContent
            }));
    
            setSearch(list);
            setShowSearch(true);
          });
      } else {
        setSearch([]);
        setShowSearch(false);
      }
    }
    
    const debouncedOnChange = useMemo(() => debounce(onChange, 300), []);
    
    ...
    
    <input
      type="text"
      aria-label="Search through site content"
      placeholder="Search your keywords"
      onChange={(e) => debouncedOnChange(e.target.value)} // <-- use debounced handler
    />
    

    【讨论】:

    • 顺便说一句 useMemo 只是为了优化对吧?
    • @ShoaibAhmed 是的。由于这是一个函数组件,因此您通常不希望在每次渲染时重新声明去抖动回调。我确实在没有 useMemo 钩子的代码盒中尝试了这个,它似乎仍然有效,但我怀疑这只是因为输入是不受控制的输入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2020-03-09
    • 1970-01-01
    相关资源
    最近更新 更多