You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Firebase v9 Firestore自动补全点击写入空白问题求助

问题描述

使用ReactJS、Firestore - Firebase v9开发。

我用纯React搭建了网页自动补全搜索栏,该问题已困扰我至少一个月:能否让该自动补全输入框与Firestore联动?即用户输入例如“elepha”时,显示包含“elephant”的建议(此部分已实现),用户点击“elephant”建议项后,将该词写入Firestore。

由于网上无相关解决方案,我想知道该需求是否可行。

我的简易自动补全栏代码(animals_data为存储动物名称的文件):
我尝试添加onClick={pleaseSend}(基础addDoc函数),但点击建议项后,Firestore中仅存入空白值""。

<SearchBar data={animals_data} />

过滤代码如下:

function SearchBar({ placeholder, data }) {
  const [filteredData, setFilteredData] = useState([]);
  const [wordEntered, setWordEntered] = useState("");
  const [newAnswer, setAnswer] = useState("")
  const [users, setUsers] = useState([]);
  
  const usersCollectionRef = collection(db, "Answers")
  const createUser = async () => {
    await addDoc(usersCollectionRef, {name: newAnswer}).then(()=>{
      window.location.reload()
    }).catch((err)=>{
      console.log(err)
    })
  };  


  const handleFilter = (event) => {
    const searchWord = event.target.value;
    setWordEntered(searchWord);
    const newFilter = data.filter((value) => {
      return value.full_name.toLowerCase().includes(searchWord.toLowerCase());
    });

    if (searchWord === "") {
      setFilteredData([]);
    } else {
      setFilteredData(newFilter);
    }
  };

  const clearInput = () => {
    setFilteredData([]);
    setWordEntered("");
  };

  return (
    <div className="search">
      <div className="searchInputs">
        <input
          type="text"
          placeholder={placeholder}
          value={wordEntered}
          onChange={handleFilter}
        />
        
      </div>
      {filteredData.length !== 0 && (
        <div className="dataResult">
          {filteredData.slice(0, 15).map((value, key) => {
            return (
              <a className="dataItem" onClick={createUser} target="_blank">
                <p>{value.full_name} </p>
              </a>
            );
          })}
        </div>
      )}
    </div>
  );
}

export default SearchBar;

解决方案

需求可行性

完全可行,你遇到的空白值问题是因为点击建议项时,没有将选中的动物名称传递给Firestore写入函数,导致newAnswer状态始终为空。

具体修复步骤

  1. 传递选中的名称到写入函数
    在渲染建议项的map方法中,修改onClick事件,将当前项的value.full_name作为参数传入createUser:

    <a className="dataItem" key={key} onClick={() => createUser(value.full_name)}>
      <p>{value.full_name}</p>
    </a>
    

    (注:移除了不必要的target="_blank",避免意外跳转;同时添加key属性符合React列表渲染规范)

  2. 修改写入函数接收参数
    更新createUser函数,直接使用传入的选中名称写入Firestore,无需依赖newAnswer状态:

    const createUser = async (selectedName) => {
      try {
        await addDoc(usersCollectionRef, { name: selectedName });
        window.location.reload(); // 若无需刷新页面可删除此行
      } catch (err) {
        console.error(err);
      }
    };
    
  3. 清理冗余状态
    删除未使用的newAnswer状态:

    // 移除该行
    const [newAnswer, setAnswer] = useState("")
    

修复后完整代码

function SearchBar({ placeholder, data }) {
  const [filteredData, setFilteredData] = useState([]);
  const [wordEntered, setWordEntered] = useState("");
  const [users, setUsers] = useState([]);
  
  const usersCollectionRef = collection(db, "Answers")
  const createUser = async (selectedName) => {
    try {
      await addDoc(usersCollectionRef, { name: selectedName });
      window.location.reload();
    } catch (err) {
      console.error(err);
    }
  };  


  const handleFilter = (event) => {
    const searchWord = event.target.value;
    setWordEntered(searchWord);
    const newFilter = data.filter((value) => {
      return value.full_name.toLowerCase().includes(searchWord.toLowerCase());
    });

    if (searchWord === "") {
      setFilteredData([]);
    } else {
      setFilteredData(newFilter);
    }
  };

  const clearInput = () => {
    setFilteredData([]);
    setWordEntered("");
  };

  return (
    <div className="search">
      <div className="searchInputs">
        <input
          type="text"
          placeholder={placeholder}
          value={wordEntered}
          onChange={handleFilter}
        />
      </div>
      {filteredData.length !== 0 && (
        <div className="dataResult">
          {filteredData.slice(0, 15).map((value, key) => {
            return (
              <a className="dataItem" key={key} onClick={() => createUser(value.full_name)}>
                <p>{value.full_name}</p>
              </a>
            );
          })}
        </div>
      )}
    </div>
  );
}

export default SearchBar;

额外优化建议

  • 点击建议项后,可将选中名称填充到输入框:在createUser函数中添加setWordEntered(selectedName),同时调用setFilteredData([])关闭下拉列表。
  • 移除window.location.reload(),改用状态更新实现页面数据同步,提升用户体验。

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:48:27