【问题标题】:How can i filter my State with onChange in reactJs?如何在 reactJs 中使用 onChange 过滤我的状态?
【发布时间】:2021-03-19 01:44:41
【问题描述】:

我想用onChange 事件过滤我的产品。例如,如果我只搜索“a”,我想查看所有包含“a”的产品如果我删除“a”或我刚刚搜索过的任何内容,我希望在不刷新页面的情况下返回所有产品。

下面是我的代码;它确实过滤了我搜索的内容,如果我删除了我输入的内容,它不会把所有产品都还给我。

我知道我正在用我制定的解决方案改变我的products,但我想知道如何解决这个问题。

import React, { useEffect, useState } from "react";
import { getProductKinds, getProducts } from "../lookup";

function Products() {

  //const [count, setCount] = useState(0);
  const [products, setProducts] = useState([]);
  useEffect(() => {

    const myCallBack = (response, status) => {
      if (status === 200) {
        console.log("products resnpose:", response);
        setProducts(response);
      }
    };
    
    getProducts(myCallBack);
  },[] );
  const filterProducts = (event) => {
    let filterText = event.target.value;
    let tempProducts = [...products];
    setProducts(tempProducts.filter(product => {
      console.log(product.name.includes(filterText));
      if (product.name.includes(filterText)) return product;
    }))
    
  }

  return (
    <div className="products-page">
      <div className="card-filters">
        <form>
          <div class="form-search col mt-5 ml-2 ">
            <input
              onChange = {filterProducts}
              type="text"
              name="text"
              class="form-control"
              placeholder="Search"
            />
          </div>

          <p></p>
          <h5 clas>Category</h5>
          <hr></hr>
          <div className="form-buttons container mt-4">
            <button className="btn btn-outline-secondary btn-sm">All</button>
            <p></p>
            <button className="btn btn-outline-secondary btn-sm">
              Electronic
            </button>
            <p></p>
            <button className="btn btn-outline-secondary btn-sm">
              Furniture
            </button>
            <p></p>
            <button className="btn btn-outline-secondary btn-sm">Dining</button>
            <hr></hr>
          </div>
          <div>
           <div className ="form-price">
           <h5>Price</h5>
           <p > 2790.99$</p>
           <input type="range" name="price" min="0" max="309999" value="309999">
              </input>
              </div> 

          </div>
          <hr></hr>
        </form>
      </div>
      <div className="card-group container">
        {products.map((product) => {
          return (
            <div>
              <div className="card shadow" style={{ width: "18rem" }}>
                <img
                  className="card-img-top"
                  src="https://dl.airtable.com/.attachmentThumbnails/65708b701baa3a84883ad48301624b44/2de058af"
                  alt="Card image cap"
                />
                <a class="link" href="/products/recroK1VD8qVdMP5H">
                  <svg
                    stroke="currentColor"
                    fill="white"
                    stroke-width="0"
                    viewBox="0 0 512 512"
                    height="1em"
                    width="1em"
                    xmlns="http://www.w3.org/2000/svg"
                  >
                    <path d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"></path>
                  </svg>
                </a>
                <div className="card-footer">
                  <p className="card-text">{product.name}</p>
                  <p className="card-price" style={{ float: "right" }}>
                    {product.price}$
                  </p>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
export default Products;


【问题讨论】:

  • 你在这里改变了状态。即使您使用解构复制数组,任何嵌套元素仍然是对存储在 state 中的元素的引用。此外,由于您正在过滤和设置状态数组,因此在第二个过滤器上它只查看之前过滤的事件,而不是整个列表,因此没有完整的集合可以从中获取它们。

标签: javascript reactjs react-hooks jsx


【解决方案1】:

我会将我的响应数据放在 2 个数组中,setAllProducts(response);setProducts(response);

如果您的输入为空,则通过 setProducts(allProducts) 显示所有产品,如果输入为 1 个或更多字符,则通过 setProducts(YOUR_FILTER_HERE) 显示产品

我可能会使用 2 个数组来做类似的事情:

const myCallBack = (response, status) => {
      if (status === 200) {
        console.log("products resnpose:", response);
        setAllProducts(response);
        setProducts(response);
      }
};

const filterProducts = (event) => {
    let filterText = event.target.value;
    if (event.target.value.length === 0) {
      setProducts(allProducts);
    } else {
      setProducts(products.filter(product => {
        console.log(product.name.includes(filterText));
        if (product.name.includes(filterText)) return product;
      }))
    }
}

【讨论】:

    【解决方案2】:

    它不会重置为默认值,因为您一直在更改源列表。尝试做这样的事情:

    const [filteredProducts, setFilteredProducts] = useState(null)
    useEffect(() => {
      setFilteredProducts(products)
    }, [products])
    const filterProducts = (event) => {
        
        let filterText = event.target.value;
        let tempProducts = [...products];
        setFilteredProducts(tempProducts.filter(product => {
          console.log(product.name.includes(filterText));
          if (product.name.includes(filterText)) return product;
        }))
        
      }
    
    

    然后将filteredProducts 用作您的input

    【讨论】:

      【解决方案3】:

      filterProducts 中,您正在用过滤后的状态覆盖状态,因此当您删除搜索查询时,它会尝试搜索该状态中不再存在的项目。

      要克服这个问题,您可以使用React.useMemo 执行过滤,同时保留您从服务器检索到的状态...

      const [products, setProducts] = useState([]);
      const [filterText, setFilter] = useState("");
      
      const filterProducts = (event) => {
          setFilter(event.target.value);
      }
      
      const filtered = React.useMemo(() => {
          return products.filter(product => {
            return filterText.length > 0 ? product.name.includes(filterText) : true;
          })
      }, [filterText, products]);
      
      // Use the filtered variable
      return (
          {filtered.map((product) => {
      );
      

      【讨论】:

      • 我真的很感动。我猜memo 可能真的很有用,但我不知道。谢谢。
      • @AliZiyaÇEVİK 派上用场了!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      • 2022-12-21
      相关资源
      最近更新 更多