简体   繁体   English

尝试使用 useState 过滤数据时在 React 中重新渲染问题

[英]Re-rending Propblem in React when trying to filter the data using useState

This is App.js.这是 App.js。 I am trying to change the HouseDetails with useState Hook, whenever I tried its showing re-rendring problem.每当我尝试显示重新渲染问题时,我都试图用useState Hook 更改 HouseDetails。

import "./App.css";
import Card from "./components/Card";
import NavBar from "./components/NavBar";
import Header from "./components/Header";
import { HiChevronDown } from "react-icons/hi";
import { useState, useMemo } from "react";
import HouseDetails from "./components/RealState/HouseDetails";

function App() {
  const [items, setItems] = useState(HouseDetails);
  // const [items, setItems] = useState(HouseDetails);
  
  
  const filterHouse = (e) => {

    const newHouse = e.filter((f) => {
      f.name.includes('Collsmith'); return 1;
    })

    // dont call setItems inside useMemo
    // it triggers another render 
    // which triggers another useMemo call
    // setItems(newHouse);
    
  }
  
  
  const updatedItems = useMemo(() => filterHouse(items), [items]);
  setItems(updatedItems);

  return (
    <div className="w-full justify-center">
      <Header />
      <main className="w-[76%] m-auto">
        <div className="my-14 py-2">
          <div className="sm:flex justify-between items-center">
            <ul>
              <li className="hidden sm:block lg:text-4xl font-semibold">
                Search properties to rent
              </li>
            </ul>
            <ul className="flex items-center justify-between border-2 border-gray-300 px-3 py-2 rounded-md text-gray-600">
              <li className="font-semibold">
                <input
                  type="search"
                  className="outline-none"
                  placeholder="Search with Search Bar"
                />
              </li>
              <li>
                <HiChevronDown />
              </li>
            </ul>
          </div>
          <NavBar />
        </div>

        {/* main-content */}

        <div className="grid xl:grid-cols-3 lg:grid-row-3 md:grid-cols-2 lg:gap-8 md:gap-6 sm:gap-4">
          <Card items={items} />
        </div>
      </main>
    </div>
  );
}

export default App;

And this is Card.js这是 Card.js

import React, { useState, useMemo } from "react";
import { FiHeart } from "react-icons/fi";
import { MdBed } from "react-icons/md";
import { BiBath, BiArea } from "react-icons/bi";

const Card = ({ items }) => {

  return items && items.map((elem) => {
    const { id, image, name, location, price, beds, bathrooms, area } = elem;
    return (
      <article key={id} className="flex-col justify-center rounded-lg shadow-md max-w-xl">
        <div className="rounded-lg">
          <img src={require('./house1.jpg')} alt="" className="rounded-lg h-72 w-full" />
        </div>
        <div className="flex-col justify-center px-4 py-2 space-y-3">
          <div className="flex-col justify-center space-y-1">
            <ul className="flex justify-between items-center">
              <li className="text-purple-600 font-bold text-2xl">
                ${price}
                <span className="text-sm text-gray-400 font-semibold">
                  /month
                </span>
              </li>
              <li className="cursor-pointer p-2 rounded-full border-2 border-gray-300 text-xl text-purple-600">
                <FiHeart />
              </li>
            </ul>
            <ul>
              <li className="font-bold text-gray-600 text-2xl">{name}</li>
            </ul>
            <ul>
              <li className="text-gray-400 text-sm">{location}</li>
            </ul>
          </div>
          <div className="flex justify-between items-center py-3">
            <ul className="flex justify-between items-center">
              <li className="text-xl pr-2 text-purple-600">
                <MdBed />
              </li>
              <li className="text-xs text-gray-400 font-semibold">
                {beds} Beds
              </li>
            </ul>
            <ul className="flex justify-between items-center">
              <li className="text-xl pr-2 text-purple-600">
                <BiBath />
              </li>
              <li className="text-xs text-gray-400 font-semibold">
                {bathrooms} Bathrooms
              </li>
            </ul>
            <ul className="flex justify-between items-center">
              <li className="text-xl pr-2 text-purple-600">
                <BiArea />
              </li>
              <li className="text-xs text-gray-400 font-semibold">
                {area} m2
              </li>
            </ul>
          </div>
        </div>
      </article>
    );
  });
};

export default Card;

Still showing error, re-rendoring.仍然显示错误,重新渲染。

Quick fix comment setItems(newHouse);快速修复评论setItems(newHouse); inside filterHouse内部过滤室

 const [items, setItems] = useState(HouseDetails);


  const filterHouse = () => {

    const newHouse = items.filter((item) => {
      return item.name.includes('Collsmith')
    })
    return newHouse

    // dont call setItems inside useMemo
    // it triggers another render 
    // which triggers another useMemo call
    // setItems(newHouse);

  }


  const updatedItems = useMemo(() => filterHouse(items), [items]);
  // do you want to filter based on text
  //const updatedItems = useMemo(() => filterHouse(items, filterString), [items, filterString]);

I think you dont want to update HouseDetails after filtering because when you do filtering again, some of the initial items will be removed, which will give you wrong results我想你不想在过滤后更新 HouseDetails 因为当你再次过滤时,一些初始项目将被删除,这会给你错误的结果

and string.includes is case sensitive string.includes区分大小写

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM