开发者问题收集

React – 无法正确过滤数组

2020-07-25
540

我正在尝试向我的项目添加过滤器功能。从包含不同语言的条目列表中,创建所有语言的数组。用户应该能够单击一种语言并让 React 过滤器仅显示包含该语言的条目。但是,在运行 filterIt 函数时,我似乎无法正确更新 entries 状态。如果我在运行 setEntries(filtered) 后 console.log 条目,结果是一样的。

const Archive = () => {
  const [entries, setEntries] = useState([]);
  let dreamFilter = [];

  //get all entries from firestore
  useEffect(() => {
    const unsubscribe = firebase
      .firestore()
      .collection("entries")
      .onSnapshot((snapshot) => {
        const newEntries = snapshot.docs.map((doc) => ({
          id: doc.id,
          ...doc.data(),
        }));
        setEntries(newEntries);
      });
    return () => unsubscribe();
  }, []);

  //after entries are loaded, create filter of all languages for 'dream'
  if (entries.length > 0) {
    const categoryMap = Object.values(entries)
      .reduce(
        (concatedArr, item) => concatedArr.concat(Object.entries(item)),
        []
      )
      .reduce((result, [category, values]) => {
        result[category] = result[category] || [];
        result[category] = result[category].concat(values);
        return result;
      }, {});

      dreamFilter = categoryMap.dream.filter(
        (item, pos) => categoryMap.dream.indexOf(item) === pos
      );
  }

  function filterIt(value) {
    const filtered = entries.filter(entry => ({
      ...entry,
      filtered: entry.dream.includes(value)
    }));
    console.log("filtered results = " + JSON.stringify(filtered));
    setEntries(filtered);
    return filtered;
  }

  return (
    <>
      <Navigation />
      <ul>
        {dreamFilter.map((language, i) => (
          <li key={i}>
            <a href="/" onClick={(value) => { filterIt(value); value.preventDefault(); }}>{language}</a>
          </li>
        ))}
      </ul>
      <ArchiveContainer>
        {entries.map((entry) => (
          <div key={entry.id}>
            <a href={"/entry/" + entry.id}>
              <h5>{entry.id}</h5>
              <p>{entry.dream}</p>
            </a>
          </div>
        ))}
      </ArchiveContainer>
    </>
  );
}
2个回答

Filter 方法应返回 true 或 false。更多信息请阅读 此处 。 如果您想要将一个数组转换为另一个对象的数组,请使用 map

您需要将 filter 方法修改为如下形式:

const filtered = entries.filter(entry => entry.dream.includes(value));
Yash Joshi
2020-07-25

在功能组件中,您无法直接更新状态。 假设您尝试在 entries 数组中添加 filtered: true/false array.filter 用于通过返回 true/false 从数组中添加或删除对象。

function filterIt(value) {
 setEntries(entryList => entryList.map(item => ({
   ...item,
   filtered: item.dream.includes(value)
 })));
}
Vishwadeep Kapoor
2020-07-25