Angie
Angie

Reputation: 105

React giving me Error: Too many re-renders. React limits the number of renders to prevent an infinite loop

The handleSortByChange function gives me an error on the browser stating that “Too many re-renders. React limits the number of renders to prevent an infinite loop.” However, on the terminal, it indicates that compliled successfully

import React, {useState} from 'react';
import './SearchBar.css';

const sortByOptions = {
    'Best Match': 'best_match',
    'Highest Rated': 'rating',
    'Most Reviewed': 'review_count'
}

function SearchBar() {
    const [ sortBy, setSortBy ] = useState('best_match')

    const getSortByClass = (sortByOption) => {
        if(sortBy === sortByOption) {
            return 'active';
        } else {
            return '';
        }
    }

    const handleSortByChange = (sortByOption) => {
        setSortBy(sortByOption);
    }

    const renderSortByOptions = () => {
        return Object.keys(sortByOptions).map((sortByOption) => {
            let sortByOptionValue = sortByOptions[sortByOption];
            return <li onClick={handleSortByChange(sortByOptionValue)} className={getSortByClass(sortByOptionValue)} key={sortByOptionValue}>{sortByOption}</li>
        })
    }

    return(
        <div className="SearchBar">
            <div className="SearchBar-sort-options">
                <ul>
                    {renderSortByOptions()}
                </ul>
            </div>
            <div className="SearchBar-fields">
                <input placeholder="Search Businesses" />
                <input placeholder="Where?" />
            </div>
            <div className="SearchBar-submit">
                {/* <a href="#">Let's Go</a> */}
                {/* <button>Let's Go</button> */}
            </div>
        </div>
    )
}

export default SearchBar;

Upvotes: 0

Views: 143

Answers (2)

Ketan Ramteke
Ketan Ramteke

Reputation: 10675

On your <li> tag you are directly calling the method like,

onClick={handleSortByChange(sortByOptionValue)}, which will set the state and rerender will be triggered, the same thing will happen again in this render cycle too, and thus the infinite loop.

instead do following:

<li
          onClick={()=>handleSortByChange(sortByOptionValue)}
          className={getSortByClass(sortByOptionValue)}
          key={sortByOptionValue}
        >

in this way, the handleSortByChange(sortByOptionValue) will only get executed when the <li> element is clicked.

import React, { useState } from "react";
// import './SearchBar.css';

const sortByOptions = {
  "Best Match": "best_match",
  "Highest Rated": "rating",
  "Most Reviewed": "review_count"
};

function SearchBar() {
  const [sortBy, setSortBy] = useState("best_match");

  const getSortByClass = sortByOption => {
    if (sortBy === sortByOption) {
      return "active";
    } else {
      return "";
    }
  };

  const handleSortByChange = sortByOption => {
    setSortBy(sortByOption);
  };

  const renderSortByOptions = () => {
    return Object.keys(sortByOptions).map(sortByOption => {
      let sortByOptionValue = sortByOptions[sortByOption];
      return (
        <li
          onClick={()=>handleSortByChange(sortByOptionValue)}
          className={getSortByClass(sortByOptionValue)}
          key={sortByOptionValue}
        >
          {sortByOption}
        </li>
      );
    });
  };

  return (
    <div className="SearchBar">
      <div className="SearchBar-sort-options">
        <ul>{renderSortByOptions()}</ul>
      </div>
      <div className="SearchBar-fields">
        <input placeholder="Search Businesses" />
        <input placeholder="Where?" />
      </div>
      <div className="SearchBar-submit">
       
      </div>
    </div>
  );
}

export default SearchBar;

Working example: Stackblitz

Upvotes: 1

gospecomid12
gospecomid12

Reputation: 1012

try this on the onClick function instead:

{() => onClick={handleSortByChange(sortByOptionValue)}

Upvotes: 1

Related Questions