0

I have the following two components.

Brands.js is a parent component that contains the SearchField component and passes a few props to it. I'll explain each prop:

  • brands is a list of Brand entities each containing an Id and a Name,
  • searchableItems is a list of Brand entities converted to an array of searchable items
  • setFilteredItems is a useState returned function that sets the filteredItems variable used by a table component
// I'm cutting away most of the code done in this component, 
// but if necessary will expand this section.
...

<SearchField 
    wrapperClassName="ms-auto me-2 h-100"
    inputClassName={"form-control-sm"}
    items={brands}
    searchableItems={searchableItems}
    setFilteredItems={setFilteredItems}
    itemIdResolver={(item) => item.id}
    placeholder="Search for brand..."
/>

...

SearchField.js is a child component that renders a search input above the table in Brands.js component.

import React, {useEffect, useState} from 'react';
import {
    Input
} from 'reactstrap';

export default function SearchField({ inputClassName, wrapperClassName, items, itemIdResolver, searchableItems, setFilteredItems, style, placeholder }) {
    if (!inputClassName) inputClassName = '';
    if (!wrapperClassName) wrapperClassName = '';
    if (!itemIdResolver) itemIdResolver = (item) => item.id;
    
    const [filterText, setFilterText] = useState("");

    useEffect(() => {
        let filteredSearchableItems = searchableItems?.filter(
            searchableItem => 
                searchableItem.searchString.indexOf(filterText.toLowerCase()) !== -1
        );
        setFilteredItems(
            items?.filter(
                item => filteredSearchableItems?.some(fsi => fsi.id === itemIdResolver(item))
            ));
    }, [filterText, items, searchableItems, setFilteredItems, itemIdResolver]);

    return (
        <div className={"search-field-wrapper " + wrapperClassName}>
            <i className="ri-search-line"></i> 
            <Input
                type="text"
                className={inputClassName}
                placeholder={placeholder}
                value={filterText}
                onChange={e => setFilterText(e.target.value)}
                style={style}
            />
        </div> 
    )
}

The problem:

The SearchField components itemIdResolver causes the Maximum update depth exceeded error since it constantly re-renders the whole page/component.

I don't understand why fitting the itemIdResolver inside the dependency array of SearchField useEffect causes this.

Any help is appreciated.

P.S. I tried removing the resolver and that got me rid of the maximum update error, so it's definitely due to that.

leshma
  • 1
  • 2

0 Answers0