Ravenous3 using function component

I try to use function components to do the ravenous project. The handleSortByChange function gives me an error stating that “Too many re-renders. React limits the number of renders to prevent an infinite loop.”

Please help

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

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

function SearchBar() {
const [search, setSearch] = useState({
term: ‘’,
location: ‘’,
sortBy: ‘best_match’
});

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

const handleSortByChange = (sortByOption) => {
    setSearch(prev => ({
        ...prev,
        sortBy: 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;

Hello, and welcome to the forums!

You’re calling handleSortByChange() instead of assigning the function as the click event handler in renderSortByOptions(). That call updates the state and triggers a re-render, so renderSortByOptions() gets called again and repeats the process all over.

Click if you'd like some possible strategies with getting the clicked value

Since you want to access the sortByOptionValue that was clicked from within handleSortByChange(), you could include it on <li /> on the data-id attribute. Then from within handleSortByChange(), you could access it via the event parameter. For example, if you renamed your handleSortByChange()'s function parameter to evt, you could get access to data-id with evt.currentTarget.dataset.id

It’s also possible to keep it very similar to what you have right now if you wrap it in an arrow function, though I’ve read that isn’t recommended from within something that updates in the render because a new function will be created each time. Passing a function created each time to another component messes with some of their optimizations, from my understanding. However, you aren’t passing it anywhere so maybe it’s a viable option here.

Thank you so much. It helps.