首页 > 解决方案 > 在 React 中过滤时,数组项仅出现一次

问题描述

在这个 React 代码中,我想要做的是从列表中获取与 setManName 函数中的文本输入中的类型匹配的所有项目(setModeName 函数中也有一个)。它可以工作,但是当我删除文本输入并重新开始时,这些项目会消失并且不会再出现,除非我再次重新加载页面并重新开始,否则不会显示在屏幕上。我正在使用 inludes() 方法,它工作正常,但是一旦我删除一个字母或整个单词并重新开始,它就不起作用了。这里有什么问题?我应该使用不同的方法吗?像另一个 useEffect 还是什么?


import React, { useState, useEffect } from "react";
import "./style.css";

export default function App() {

  const [items, setItems] = useState([])
  const [openFilterCt, setOpenFilterCt] = useState(false)

  const [term1, setTerm1] = useState()
  const [term2, setTerm2] = useState()

  useEffect(() => {
    fetch("https://private-anon-af560a53c6-carsapi1.apiary-mock.com/cars")
      .then(res => res.json())
      .then(data => {
        setItems(data)
      })
  }, [])

  function setManName(e) {
    setTerm1(e.target.value);
    let u = items.filter(item => {
      **return item.make.includes(e.target.value)**
    })
    setItems(u)
  }

  function setModName(e) {
    setTerm2(e.target.value);
    let u = items.filter(item => {
      **return item.model.includes(e.target.value)**
    })
    setItems(u)
  }

  function hi() {
    setOpenFilterCt(!openFilterCt)
  }  

  return (
    <div>
      <h1>React Search &amp; Filter</h1>
      <div>
        <h3 onClick={hi}>Filter</h3>
        <div className={openFilterCt ? "show" : "hide"}>
          <label>
            Name of manufacturer: <input type="text" value={term1} onChange={setManName} />
          </label>
          <br />
          <label>
            Name of model: <input type="text" value={term2} onChange={setModName} />
          </label>
        </div>
      </div>
        
      {items.slice(0, 50).map((a, index) => {
        return (
          <div key={index} style={{border: "1px solid black", margin: "10px", padding: "5px"}}>
            <p>Manufacturer: {a.make[0].toUpperCase() + a.make.slice(1)}</p>
            <p>Model: {a.model}</p>
            
          </div>
        )
      })}
    </div>
  );
}

标签: javascriptarraysreactjs

解决方案


您正在覆盖 items 对象,因此即使在删除字符后,任何不在搜索中的项目也不会显示。此解决方案将动态过滤项目,而不是从数组中删除它们。

term1此外,您应该为和term2状态提供默认值。如果没有默认值,输入将从不受控制的输入切换到受控的输入,这种做法在 React 中是不鼓励的。

请参阅此 Codesandbox

import React, { useState, useEffect } from "react";
import "./style.css";

export default function App() {
  const [items, setItems] = useState([]);
  const [openFilterCt, setOpenFilterCt] = useState(false);

  const [term1, setTerm1] = useState("");
  const [term2, setTerm2] = useState("");

  useEffect(() => {
    fetch("https://private-anon-af560a53c6-carsapi1.apiary-mock.com/cars")
      .then((res) => res.json())
      .then((data) => {
        setItems(data);
      });
  }, []);

  function setManName(e) {
    setTerm1(e.target.value);
  }

  function setModName(e) {
    setTerm2(e.target.value);
  }

  function filterItems(item) {
    if (term1 && !item.make.includes(term1)) return false;
    if (term2 && !item.model.includes(term2)) return false;

    return true;
  }

  function hi() {
    setOpenFilterCt(!openFilterCt);
  }

  return (
    <div>
      <h1>React Search &amp; Filter</h1>
      <div>
        <h3 onClick={hi}>Filter</h3>
        <div className={openFilterCt ? "show" : "hide"}>
          <label>
            Name of manufacturer:{" "}
            <input type="text" value={term1} onInput={setManName} />
          </label>
          <br />
          <label>
            Name of model:{" "}
            <input type="text" value={term2} onInput={setModName} />
          </label>
        </div>
      </div>

      {items
        .filter(filterItems)
        .slice(0, 50)
        .map((a, index) => {
          return (
            <div
              key={index}
              style={{
                border: "1px solid black",
                margin: "10px",
                padding: "5px"
              }}
            >
              <p>Manufacturer: {a.make[0].toUpperCase() + a.make.slice(1)}</p>
              <p>Model: {a.model}</p>
            </div>
          );
        })}
    </div>
  );
}


推荐阅读