4

I have a wrapper component around a search bar that fetches suggestions with each keystroke and then searches either when a suggestion is chosen or the user hits enter/search. Upon choosing a search value, I want to persist that search item to local storage, so that I can show it on focus, much like Google. Here is a snippet of my component

export default function App() {
    const [results, resultsLoading, resultsError, setParams] = useFetch();
    const [suggestions, ,suggestionsError, setSuggestionsParams] = useFetch();
    const [showSearchSuggestions, setShowSearchSuggestions] = useState<boolean>(true);
    const [recentSearches, setRecentSearches] = useLocalStorage('recent_searches', []);
    const [searchAttributes, setSearchAttributes] = useState<SearchAtrributesInterface>({
        value: '',
        fetchType: SEARCH_FETCH_TYPES.SUGGESTIONS
    });

    useEffect(() => {
        const getSearchSuggestions = () => setSuggestionsParams(getAutoCompleteURL(searchAttributes.value));
        const getSearchResults = () => {
            setParams(getSearchURL(searchAttributes.value));
            setShowSearchSuggestions(false);
        };

        if (searchAttributes.value) {
            if (searchAttributes.fetchType === SEARCH_FETCH_TYPES.SUGGESTIONS) {
                getSearchSuggestions();
            } else {
                getSearchResults();
                setRecentSearches([searchAttributes.value, ...recentSearches])
            }
        }
    }, [searchAttributes, setParams, setSuggestionsParams]);

    return ( ... );
};

This works fine, but then I get hit with the linting warning: React Hook useEffect has missing dependencies: 'recentSearches' and 'setRecentSearches'. Either include them or remove the dependency array react-hooks/exhaustive-deps. Upon adding those two into the dependency array, I get stuck in an infinite loop because of course recentSearches's state is getting set, causing it to re-render and so on. I'd like to find a solution as oppose to adding // eslint-disable-next-line because I feel there is something truly wrong that I am doing. Does anyone know what I could do differently to prevent the infinite loop and prevent the linter warning?

2
  • Don't bother much on react-hooks/exhaustive-deps. It is only logical if you want to update the values when the dependencies change. Consider it as a suggestion and not a requirement. you might want to do something only once and have an empty [] as dependency. This would also throw a warning, though it is pointless Commented Oct 31, 2019 at 12:58
  • There are so many things happening in one effect. Probably it's best to separate them into multiple effects. Commented Oct 31, 2019 at 13:48

1 Answer 1

1

There ware two things to it.

Since you wish to make use of the existing state value to update the same state you should use callback approach

setRecentSearches(prevRececentSearches => ([searchAttributes.value, ...prevRececentSearches]));

Also when you are absolutely sure that you haven't missed any dependency, you can disable the warning. Please check this post for more details: How to fix missing dependency warning when using useEffect React Hook?

Sign up to request clarification or add additional context in comments.

2 Comments

Cool thanks for the suggestion. Yeah I have seen some stuff where people said you shouldn't take the linter warnings too seriously, but I feel like you always should or they wouldn't be there. Glad to know the jury's out on this one though. Thanks!
the linter for this isn't perfect and it wouldn't know what you want and don't want. Linter here is to prompt you is you are missing anything by mistake and not to force it to add everything that is a dependency

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.