简体   繁体   中英

Difference between react hooks returning from useEffect

I want to migrate my code from class to function in react

I was trying to understand the difference between these two react hooks

export const useEffectExceptOnMount = (effect: () => void, dependencies: Array<any>) => {
  const mounted = useRef(false)
  useEffect(() => {
    if (mounted.current) {
      effect()
      return
    } else {
      mounted.current = true
    }
  }, dependencies)

  // Reset on unmount for the next mount.
  useEffect(() => {
    return () => {
      mounted.current = false
    }
  }, [])
}

And

export const useEffectExceptOnMount = (effect: () => void, dependencies: Array<any>) => {
  const mounted = useRef(false)
  useEffect(() => {
    if (mounted.current) {
      return () => {
       effect()
      }
    } else {
      mounted.current = true
    }
  }, dependencies)

  // Reset on unmount for the next mount.
  useEffect(() => {
    return () => {
      mounted.current = false
    }
  }, [])
}

(notice how effect() is called) here..

When they are used like this in a component like this?

  useEffectExceptOnMount(() => {
    callUpdateApi()
  }, [auth, person])

The difference is in the first version effect is run every time the dependencies are changed and consequently the useEffect runs.

In the second one though the effect is run during "effect clean up". Meaning it runs when new effect comes in and react cleans up previous effect. To see better use both at the same time:

import React, { useState, useEffect, useRef } from "react";

// custom hook to refer previous state
export const useEffectExceptOnMountA = (effect, dependencies) => {
  const mounted = useRef(false);
  useEffect(() => {
    if (mounted.current) {
      return () => {
        effect();
      };
    } else {
      mounted.current = true;
    }
  }, dependencies);

  // Reset on unmount for the next mount.
  useEffect(() => {
    return () => {
      mounted.current = false;
    };
  }, []);
};

export const useEffectExceptOnMountB = (effect, dependencies) => {
  const mounted = useRef(false);
  useEffect(() => {
    if (mounted.current) {
      effect();
      return;
    } else {
      mounted.current = true;
    }
  }, dependencies);

  // Reset on unmount for the next mount.
  useEffect(() => {
    return () => {
      mounted.current = false;
    };
  }, []);
};


export default function Parent() {
  let [s, set] = useState(0);
  useEffectExceptOnMountA(() => {
    console.log("A");
  }, [s]);

  useEffectExceptOnMountB(() => {
    console.log("B");
  }, [s]);

  return (
    <>
      <button onClick={() => set((s) => s + 1)}>Go</button>
    </>
  );
}

Here once the Parent is rendered if you click on Go button, first time you see:

B

But if you click for the second time then the console looks like:

B  <== from previous click
A
B

Here is the codesandbox and the documentationEffects with Cleanup

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM