In this series, I will read the source code of ahooks, which is used to familiarized myself with the writing method of custom hooks, and improve my ability to write custom hooks.
In order to distinguish it from the original comments of the code, the personal understanding section uses the beginning of ///, which is not related to the triple slash instruction, just to distinguish it.
Review past
- Ahooks source code interpretation series
- Ahooks Source Code Interpretation Series – 2
- Ahooks Source Code Interpretation series – 3
- Ahooks Source Code Interpretation series – 4
- Ahooks Source Code Interpretation series – 5
- Ahooks Source Code Interpretation series – 6
- Ahooks Source Code Interpretation series – 7
The series of articles is already the eighth, it seems that my strength is too strong, the previous 7 have not been pointed out mistakes, then I will continue to keep it. Hooks for LifeCycle section today.
LifeCycle
useMount
Simulate componentDidMount(), run only on first render.
import { useEffect } from 'react';
const useMount = (fn: () => void) = > {
UseEffect is used to implement lifecycle related hooks
useEffect(() = > {
fn(); /// Note that there is no return, so no cleanup is performed} []); };export default useMount;
Copy the code
useUnmount
Simulates componentWillUnmount(), which runs only when the component is unmounted.
import { useEffect } from 'react';
import usePersistFn from '.. /usePersistFn';
import { isFunction } from '.. /utils';
const useUnmount = (fn: any) = > {
const fnPersist = usePersistFn(fn);
useEffect(
() = > () = > {
if(isFunction(fnPersist)) { fnPersist(); }}, []); };export default useUnmount;
Copy the code
useUnmountedRef
“Have you gone?
Returns the flag bit that indicates whether the component is uninstalled.
import { useRef, useEffect } from 'react';
const useUnmountedRef = () = > {
const unmountedRef = useRef(false);
useEffect(() = > {
return () = > {
/// The dependency array is empty, so it is only true when the component is unloaded
unmountedRef.current = true; }; } []);return unmountedRef;
};
export default useUnmountedRef;
Copy the code
useTrackedEffect
“You see that this is the case.”
Useeffects that provide specific change dependencies
import { useEffect, useRef, DependencyList } from 'react';
const useTrackedEffect = (effect, deps? : DependencyList) = > {
const previousDepsRef = useRef<DependencyList>();
/// compare dependency changes to use! == To determine if there is a change, return the index of the change item in the dependency list
const diffTwoDeps = (deps1, deps2) = > {
//Let's do a reference equality check on 2 dependency list.
//If deps1 is defined, we iterate over deps1 and do comparison on each element with equivalent element from deps2
//As this func is used only in this hook, we assume 2 deps always have same length.
return deps1
? deps1.map((_ele, idx) = >(deps1[idx] ! == deps2[idx] ? idx : -1)).filter((ele) = > ele >= 0)
: deps2
? deps2.map((_ele, idx) = > idx)
: [];
};
useEffect(() = > {
let changes = diffTwoDeps(previousDepsRef.current, deps);
const previousDeps = previousDepsRef.current;
previousDepsRef.current = deps;
return effect(changes, previousDeps, deps); /// provide variable value index, previous dependency array, current dependency array to cb
}, deps);
};
export default useTrackedEffect;
Copy the code
useDebounceEffect
UseEffect with anti – shake function
import { useEffect, EffectCallback, DependencyList, useState } from 'react';
import { DebounceOptions } from '.. /useDebounce/debounceOptions';
import useDebounceFn from '.. /useDebounceFn';
import useUpdateEffect from '.. /useUpdateEffect';
import useUnmount from '.. /useUnmount';
function useDebounceEffect(effect: EffectCallback, deps? : DependencyList, options? : DebounceOptions,) {
const [flag, setFlag] = useState({});
const { run, cancel } = useDebounceFn(() = > {
setFlag({}); /// Update flag to trigger useUpdateEffect to trigger effect callback
}, options);
/// Trigger an effect on the first render
useEffect(() = > {
return run();
}, deps);
/ / / clean up
useUnmount(cancel);
useUpdateEffect(effect, [flag]);
}
export default useDebounceEffect;
Copy the code
useThrottleEffect
UseEffect with throttling function
import { useEffect, EffectCallback, DependencyList, useState } from 'react';
import { ThrottleOptions } from '.. /useThrottle/throttleOptions';
import useThrottleFn from '.. /useThrottleFn';
import useUpdateEffect from '.. /useUpdateEffect';
import useUnmount from '.. /useUnmount';
function useThrottleEffect(effect: EffectCallback, deps? : DependencyList, options? : ThrottleOptions,) {
const [flag, setFlag] = useState({});
const { run, cancel } = useThrottleFn(() = > {
setFlag({});
}, options);
useEffect(() = > {
return run();
}, deps);
useUnmount(cancel);
useUpdateEffect(effect, [flag]);
}
export default useThrottleEffect;
Copy the code
useUpdate
Simulation forceUpdate ()
import { useCallback, useState } from 'react';
const useUpdate = () = > {
const [, setState] = useState({});
return useCallback(() = > setState({}), []); /// trigger a component update by updating state when called
};
export default useUpdate;
Copy the code
useUpdateEffect
Simulate componentDidUpdate, ignoring useEffect for the first rendering version. This has nothing to do with useUpdate.
import { useEffect, useRef } from 'react';
const useUpdateEffect: typeof useEffect = (effect, deps) = > {
const isMounted = useRef(false);
useEffect(() = > {
if(! isMounted.current) { isMounted.current =true;
} else {
return effect(); /// Ignores the first render and only runs when it depends on updates
}
}, deps);
};
export default useUpdateEffect;
Copy the code
useUpdateLayoutEffect
Equivalent componentDidUpdate, ignores the first rendering version of useLayoutEffect.
Learn more about React useLayoutEffect and useEffect execution timing
/* eslint consistent-return: 0 */
import { useLayoutEffect, useRef } from 'react';
const useUpdateLayoutEffect: typeof useLayoutEffect = (effect, deps) = > {
const isMounted = useRef(false);
useLayoutEffect(() = > {
if(! isMounted.current) { isMounted.current =true;
} else {
return effect();
}
}, deps);
};
export default useUpdateLayoutEffect;
Copy the code
The above content due to my level problem is inevitable error, welcome to discuss feedback.