Abhilash Poojary
Abhilash Poojary

Reputation: 127

setstate is causing Too many re-renders

const [input, setInput] = useState("");
  const [searchedProducts, setSearchedProducts] = useState(products);
  const inputChange = (e) => {
    setInput(e.target.value);
  };
  if (input) {
    let newProducts =
      products &&
      products.filter(function (el) {
        return el.Name.toLowerCase().includes(input.toLowerCase());
      });
    setSearchedProducts([...newProducts]);
  }

here searchedProducts which is having products as initial value, my products has array of objects below is the sample:

[
    {
        "id": "HT-1000",
        "Category": "Laptops",
        "MainCategory": "Computer Systems",
        "TaxTarifCode": "1",
        "SupplierName": "Very Best Screens",
        "WeightMeasure": 4.2,
        "WeightUnit": "KG",
        "Description": "Notebook Basic 15 with 2,80 GHz quad core, 15\" LCD, 4 GB DDR3 RAM, 500 GB Hard Disc, Windows 8 Pro",
        "Name": "Notebook Basic 15",
        "DateOfSale": "2017-03-26",
        "ProductPicUrl": "https://rukminim1.flixcart.com/image/416/416/jw9ke4w0/computer/a/y/c/lenovo-na-laptop-original-imafgzg4rhdztzww.jpeg?q=70",
        "Status": "Available",
        "Quantity": 10,
        "UoM": "PC",
        "CurrencyCode": "EUR",
        "Price": 956,
        "Width": 30,
        "Depth": 18,
        "Height": 3,
        "DimUnit": "cm"
    }
]

here iam trying to filter the product array using keyword received from the input state able to filter the array, but while doing setstate getting below error: Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. have been stucked for while with this issue!!

Upvotes: 0

Views: 1165

Answers (2)

Suleman Ahmad
Suleman Ahmad

Reputation: 484

Move your if statement inside useEffect hook like this then it will only re-render once input state updated and is true.

   useEffect(()=>{
    
     if (input) {        // use if condition here 
       let newProducts =
       products &&
       products.filter(function (el) {
        return el.Name.toLowerCase().includes(input.toLowerCase());
       });
       setSearchedProducts([...newProducts]);
    }

    },[input]); //your input state will be checked and render once changed from the previous state

Upvotes: 0

tuomokar
tuomokar

Reputation: 388

You call setSearchedProducts on every render when input has a truthy value. Because the setSearchedProducts call causes a re-render you have an infinite render loop.

If you need to set the searchedProducts to state (it seems rather redundant), then you should do it in an effect hook

useEffect(() => {
  let newProducts =
    products &&
    products.filter(function (el) {
      return el.Name.toLowerCase().includes(input.toLowerCase());
  });
  setSearchedProducts(newProducts);
}, [input])

Having the input as the dependency parameter causes the hook to run only when the input changes.

Upvotes: 1

Related Questions