Search code examples
reactjsreact-hooksuse-effect

ReactHooks : Options for calling callback function of useEffect depending on why useEffect got triggered (on render or state update)


I am using plain sqlite for react native and let my mutations change a top level state variable at the source of my app tree. Now I want to udpate the lists in the screens accordingly and let them listen to that here called "stateUpdate" variable.

As I have different tables that get mutated, I just want the queries to trigger which relate to that table. Set an object into the sate variable having a property name which describes the type of query that should be triggered afterwards.

So one time I want my list components to trigger the query on mount, and after the related muations. Checking following code, i need to make two useEffect hooks, one listening with the name condition inside and one that just calls the function on render. Just using one would either fire the query whenever a mutation changed the state variable, no matter what name ( without name condition) or not consistently on mount (with name condition).

My solution seems a bit silly to me but I do not see another way. Do you might have an idea of reducing the lines of code for this a bit with a more elegant alternative?

// Every time a mutation for products takes place
  React.useEffect(() => {

   if(stateUpdate.name === "productsQuery"){

    productsQuery(db).then(dbArray => {
      setProducts(dbArray)
    })

   }
  
  }, [stateUpdate]);

  // Every time the list mounts
  React.useEffect(() => {
    
     productsQuery(db).then(dbArray => {
       setProducts(dbArray)
     })

   }, []);

Solution

  • Use a ref to indicate first/initial/mounting render. Start with an initial mount value of true so the condition runs, then set to false after the initial render so the second condition is tested on subsequent renders.

    const mountRef = useRef(true);
    
    useEffect(() => {
      if (mountRef.current || stateUpdate.name === "productsQuery") {
        mountRef.current = false;
        productsQuery(db).then(dbArray => {
          setProducts(dbArray);
        });
      }
    }, [stateUpdate]);