0

I have such a situation, I need to execute my function each time the string searchTerms and total.value is changing. Here is how it looks like

useEffect(() => {
    if (searchTerms) {
      analyticsService?.logEvent(ANALYTICS_EVENTS.SEARCH_COMPLETED, {      
        total_results: data?.hits.total.value,
        error_message: null,
      });
    }
  }, [data?.hits.total.value && searchTerms]);

But it works not as expected, I need to execute this function only when data.hits.total.value && searchTerms is changed. Not OR!

If I will make it like this

[data?.hits.total.value, searchTerms]

Then my function would log 2 times each search, but I don't need it.

How can I fix it?

Fatality99
  • 121
  • 5
  • The dependencies should be separated by a comma (`,`). See [`useEffect` usage](https://beta.reactjs.org/reference/react/useEffect#useeffect) – Shivam Jha Dec 29 '22 at 10:16
  • the syntax seems right you have to check if either of them is undefined in the console. – Ankit Dec 29 '22 at 10:24
  • @ShivamJha I already wrote that i I will put comma the my function logs 2 times each search. I need only 1 time – Fatality99 Dec 29 '22 at 10:26
  • If you are using React 18,It logs twice only in development. It should not bother you as it will log only once in prod. See [useEffect firing twice in development](https://beta.reactjs.org/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). If you are not using React 18, and still firing twice, then you need to reconsider your approach. (Make sure your linter is not showing any warning in `useEffect`) – Shivam Jha Dec 29 '22 at 10:46
  • how is this "dupe" related to OPs problem that he wants the effect only to fire after ALL deps have changed? Not when any single one of them has changed., – Thomas Dec 29 '22 at 11:29
  • @Thomas Thanks you got me right, how can I check it, any advice? – Fatality99 Dec 29 '22 at 11:44
  • 1
    I'd write a hook that extends useEffect by a function that determines if the current deps are different (enough) from the previously accepted ones. But if you want to do it right, that's a bit more than a oneliner. You have to keep track of the previous deps array and you have to manage the cleanup function manually. – Thomas Dec 29 '22 at 11:55
  • 1
    I guess, I'm thinking too general purpose, for this explicit case, this should do: `const ref = useRef([]), deps = [data?.hits.total.value, searchTerms]; useEffect(() => { if (deps.every((v, i) => v !== ref.current[i])) { ref.current = deps; /*...*/ } }, deps);` – Thomas Dec 29 '22 at 12:04
  • @Thomas Thanks, but it is still don't call the function when the data?.hits.total.value is the same as the previous one :( – Fatality99 Dec 29 '22 at 12:28
  • 1
    That's what you wanted (untill now). Then you have to change the condition to something that describes what you mean, because what you said was "when all deps have changed". `ref.current` contains the last deps that were logged, `deps` contains the current ones. Now it's up to you to create a condition that describes what the difference between the two has to be so that you want to log again. – Thomas Dec 29 '22 at 13:13
  • @Thomas thank you sm! One more question, how can I take last value of data?.hits.total.value from deps? – Fatality99 Dec 29 '22 at 13:19
  • 1
    `ref.current[0]` – Thomas Dec 29 '22 at 14:56

0 Answers0