Javascript 在React中筛选时,数组项仅出现一次

Javascript 在React中筛选时,数组项仅出现一次,javascript,arrays,reactjs,Javascript,Arrays,Reactjs,在这个React代码中,我试图从列表中获取与setManName函数中的文本输入类型匹配的所有项目(setModeName函数中也有一个)。它可以工作,但当我删除文本输入并重新开始时,这些项目将消失,不再出现,除非我重新加载页面并重新开始,否则不会显示在屏幕上。我使用的是inludes()方法,效果很好,但一旦我删除一个字母或整个单词并重新开始,它就不起作用了。这里有什么问题?我应该使用不同的方法吗?像是另一种效果还是什么 import React, { useState, useEffect

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


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>
  );
}


从“React”导入React,{useState,useffect};
导入“/style.css”;
导出默认函数App(){
const[items,setItems]=useState([])
const[openFilterCt,setOpenFilterCt]=useState(false)
const[term1,setTerm1]=useState()
const[term2,setTerm2]=useState()
useffect(()=>{
取回(“https://private-anon-af560a53c6-carsapi1.apiary-mock.com/cars")
.then(res=>res.json())
。然后(数据=>{
设置项目(数据)
})
}, [])
函数setManName(e){
setTerm1(即目标值);
设u=items.filter(item=>{
**退货项目.制造.包括(如目标值)**
})
集合项目(u)
}
函数setModName(e){
setTerm2(即目标值);
设u=items.filter(item=>{
**返回项.model.includes(例如target.value)**
})
集合项目(u)
}
函数hi(){
setOpenFilterCt(!openFilterCt)
}  
返回(
反应搜索和过滤
滤器
制造商名称:

型号名称: {items.slice(0,50).map((a,index)=>{ 返回( 制造商:{a.make[0].toUpperCase()+a.make.slice(1)}

模型:{a.Model}

) })} ); }
我刚刚为您的型号搜索修复了它,您可以对制造商搜索执行相同的操作。也许有更好的方法,但这是我解决的问题

您需要做的是保留原始列表
.filter()
实际上更改了原始列表,当响应为空时,原始数据将消失。所以我只是保留了旧数据

const [orItem, setOrItems] = useState([]);

const prevList = orItem;

  function setModName(e) {
    setTerm2(e.target.value);
    let u = prevList.filter((item) => {
      return item.model.includes(e.target.value);
    });
    setItems(u);
  }
您可以在此处看到用于模型搜索的代码:


您正在覆盖items对象,因此,即使删除了字符,也不会显示未在搜索中的任何项目。此解决方案将动态筛选项,而不是将其从阵列中删除

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

import React,{useState,useffect}来自“React”;
导入“/style.css”;
导出默认函数App(){
const[items,setItems]=useState([]);
const[openFilterCt,setOpenFilterCt]=useState(false);
const[term1,setTerm1]=useState(“”);
const[term2,setTerm2]=useState(“”);
useffect(()=>{
取回(“https://private-anon-af560a53c6-carsapi1.apiary-mock.com/cars")
.然后((res)=>res.json())
。然后((数据)=>{
设置项目(数据);
});
}, []);
函数setManName(e){
setTerm1(即目标值);
}
函数setModName(e){
setTerm2(即目标值);
}
功能过滤器项(项目){
如果(term1&&!item.make.includes(term1))返回false;
if(term2&&!item.model.includes(term2))返回false;
返回true;
}
函数hi(){
setOpenFilterCt(!openFilterCt);
}
返回(
反应搜索和过滤
滤器
制造商名称:{“}

模型名称:{“”} {项目 .过滤器(过滤器) .切片(0,50) .map((a,索引)=>{ 返回( 制造商:{a.make[0].toUpperCase()+a.make.slice(1)}

模型:{a.Model}

); })} ); }
首先,您不应该修改原始数组
。您需要创建另一个(另一个状态变量)
filteredItems
,以便可以重置为原始状态,而且我相信这里还有另一个错误
item.model.includes(e.target.value)
,如果文本为空,它将始终返回
false

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

另外,
useffect
hook应该是这样的:

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

并确保
map
覆盖
filteredItems

这里的问题是您正在重置从给定URL接收的值。您应该维护一个单独的可见性列表,您可以使用方法1。如下所示。这是我在不修改大量代码的情况下所能做的最好的事情,但是这通常是对状态的过度/错误使用。记住React之所以被称为React,是因为它在状态改变时具有惊人的反应能力。 Approach 2实现了这一点,您可以灵活地使用过滤器,并根据需要对其进行更改。你的搜索行为

// Approach 1

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

export default function App() {

  const [items, setItems] = useState([]);
  const [visibleItems, setVisibleItems] = 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);
        setVisibleItems(data);
      })
  }, [])

  function setManName(e) {
    // setTerm1(e.target.value);
    let u = items.filter(item => {
      if(e.target.value){
        return item.make.includes(e.target.value)
      }
      return true;      
    })
    setVisibleItems(u)
  }

  function setModName(e) {
    // setTerm2(e.target.value);
    let u = items.filter(item => {
      return item.model.includes(e.target.value)
    })
    setVisibleItems(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>
        
      {visibleItems.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>
  );
}
//方法1
从“React”导入React,{useState,useffect};
//导入“/style.css”;
导出默认函数App(){
const[items,setItems]=useState([]);
const[visibleItems,setVisibleItems]=useState([]);
const[openFilterCt,setOpenFilterCt]=useState(false)
const[term1,setTerm1]=useState()
const[term2,setTerm2]=useState()
useffect(()=>{
取回(“https://private-anon-af560a53c6-carsapi1.apiary-mock.com/cars")
.then(res=>res.json())
。然后(数据=>{
设置项目(数据);
设置可见项(数据);
})
}, [])
函数setManName(e){
// Approach 1

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

export default function App() {

  const [items, setItems] = useState([]);
  const [visibleItems, setVisibleItems] = 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);
        setVisibleItems(data);
      })
  }, [])

  function setManName(e) {
    // setTerm1(e.target.value);
    let u = items.filter(item => {
      if(e.target.value){
        return item.make.includes(e.target.value)
      }
      return true;      
    })
    setVisibleItems(u)
  }

  function setModName(e) {
    // setTerm2(e.target.value);
    let u = items.filter(item => {
      return item.model.includes(e.target.value)
    })
    setVisibleItems(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>
        
      {visibleItems.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>
  );
}
// Approach2
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 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
        .filter((item) => {
          return item.make.includes(term1) && item.model.includes(term2);
        })
        .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>
  );
}