Take this example,
const SelectContainer = ({ excludeIds }) => {
const queryItems = (items) => {
return items.filter((item) => !excludeIds.includes(item.id)
}
console.log("SELECT CONTAINER EXCLUDEIDS:", excludeIds);
return (
<Select queryItems={queryItems} excludeIds={excludeIds} />
);
};
const Select = ({ queryItems, excludeIds, addItem }) => {
const [items, setItems] = useState(dummyItems);
const searchResults = (value) => {
console.log("SELECT EXCLUDEIDS:", excludeIds);
return queryItems(items);
}
return <SearchSelect search={searchResults} onItemSelect={(item) => addItem(item)} />;
};
excludeIds
is updated through an API call made by the parent component of SelectContainer
. Basically, when an item is selected through Select
, addItem
will trigger some logic that will eventually update excludeIds that's passed into SelectContainer to include that added item's ID so that it's not repeated.
When excludeIds
changes from say [77]
to [77, 78]
, I would expect for queryItems
to begin excluding items that have ID's 77 and 78, but this only happens upon refresh or a forced re-render of the container and the child component.
I think something about how we're passing in a reference for queryItems
to Select
causes it not to change even when excludeIds
changes in the SelectContainer
component.
I tried printing excludeIds
before it's passed into Select
and it has the right values [77, 78]
, but printing it in Select.searchResults
function produces the wrong value [77]
. Anyone have an idea of how I can update queryItems
to update whenever excludeIds
changes?
Ended up fixing this through using React.useRef
in Select
. useRef
allows us to track a mutable reference to queryItems
that is available between renders. Every time queryItems
changes, useEffect
captures that change and we're able to store it within the reference to be used in the search function.
const Select = ({ queryItems, excludeIds, addItem }) => {
const [items, setItems] = useState(dummyItems);
const searchResults = (value) => {
return queryItems(items);
}
const queryItemsRef = React.useRef(queryItems);
React.useEffect(() => {
queryItemsRef.current = queryItems;
}, [queryItems]);
return (
<SearchSelect search={searchResults} onItemSelect={(item) => addItem(item)} />
);
};