Collection of some react hooks
yarn add @react-cmpt/hooks- useAsyncClick
- useDebounce
- useDebouncedCallback
- useDebouncedClick
- useDeepCompareCache
- useDeepEffect
- useEllipsis
- useInterval
- useLoadImg
- useMountedState
- useSupportSafeArea
- useThrottle
- useThrottleFn
- useUnmount
- useUpdate
- useUpdateEffect
Click event with loading
| option | type | default | explain | 
|---|---|---|---|
| asyncFunc | function | async function | |
| initState | Object | { loading: false } | initial loading | 
| return | type | default | explain | 
|---|---|---|---|
| callback | function | ||
| loading | boolean | ||
| error | Error | catch error | 
import { useAsyncClick } from "@react-cmpt/hooks";
const asyncFn = async () => {
  // do something
};
const Demo = ({ asyncFn }) => {
  const { callback, loading } = useAsyncClick(asyncFn);
  return <Button loading={loading} click={callback} />;
};| option | type | default | explain | 
|---|---|---|---|
| value | any | ||
| delay | number | ||
| options | Object | 
options:
| option | type | default | explain | 
|---|---|---|---|
| maxWait | number | Describes the maximum time func is allowed to be delayed before it's invoked | |
| leading | boolean | This param will execute the function once immediately when called. Subsequent calls will be debounced until the timeout expires. | |
| equalityFn | function | Comparator function which shows if timeout should be started | 
import { useDebounce } from "@react-cmpt/hooks";
const Demo = () => {
  const [text, setText] = useState("hello");
  const [value] = useDebounce(text, 1000);
  return (
    <div>
      <input
        defaultValue={"hello"}
        onChange={(e) => {
          setText(e.target.value);
        }}
      />
      <p>Actual value: {text}</p>
      <p>Debounce value: {value}</p>
    </div>
  );
};| option | type | default | explain | 
|---|---|---|---|
| callback | function | ||
| delay | number | ||
| options | Object | 
import { useDebouncedCallback } from "@react-cmpt/hooks";
const Demo = () => {
  const [value, setValue] = useState();
  // Debounce callback
  const debouncedCallback = useDebouncedCallback(
    // function
    (value) => {
      setValue(value);
    },
    // delay in ms
    1000
  );
  return (
    <div>
      <input onChange={(e) => debouncedCallback(e.target.value)} />
      <p>Debounced value: {value}</p>
    </div>
  );
};Click event with loading and debounce
| option | type | default | explain | 
|---|---|---|---|
| asyncFunc | function | async function | |
| delay | number | 0 | useDebouncedCallbackArgs["delay"] | 
| options | Object | useDebouncedCallbackArgs["options"] | 
| return | type | default | explain | 
|---|---|---|---|
| callback | function | ||
| loading | boolean | ||
| cancelDebouncedCallback | function | useDebouncedCallbackReturns["cancelDebouncedCallback"] | |
| callPending | function | useDebouncedCallbackReturns["callPending"] | |
| error | Error | catch error | 
import { useDebouncedClick } from "@react-cmpt/hooks";
const asyncFn = async () => {
  // do something
};
const Demo = ({ asyncFn }) => {
  const { callback, loading } = useDebounceClick(asyncFn);
  return <Button loading={loading} click={callback} />;
};| option | type | default | explain | 
|---|---|---|---|
| value | any | 
import { useDeepCompareCache } from "@react-cmpt/hooks";
const obj1 = { a: 1, b: { b1: 2 } };
const obj2 = { a: 1, b: { b1: 2 } };
const Demo = () => {
  const obj = useDeepCompareCache(obj1);
  console.log(obj1 === obj2); // false
  console.log(obj === obj1); // true
  console.log(obj === obj2); // true
  // ...
};import { useDeepCompareCache } from "@react-cmpt/hooks";
const Demo = () => {
  // Deep comparison React.useEffect
  useEffect(() => {
    // ...
  }, useDeepCompareCache([A, B]));
  // Deep comparison React.useCallback
  const callback = useCallback(() => {
    // ...
  }, useDeepCompareCache([A, B]));
  // ...
};Deep comparison React.useEffect
| option | type | default | explain | 
|---|---|---|---|
| effect | function | Imperative function that can return a cleanup function | |
| deps | Array | If present, effect will only activate if the values in the list change. | 
import { useDeepEffect } from "@react-cmpt/hooks";
const Demo = ({ value: Object }) => {
  useDeepEffect(() => {
    // do something
  }, [value]);
  // ...
};Hidden overflow content and get overflow status
| option | type | default | explain | 
|---|---|---|---|
| content | ReactNode | - | Overflow content. The expectation is String | 
| options.lineClamp | number | string | - | The -webkit-line-clampCSS property | 
| options.debouncedWait | number | 500 | The number of milliseconds to delay. useDebouncedCallback | 
| options.wrapperClassName | string | - | Wrapper element className | 
| options.wrapperStyle | Object | - | Wrapper element style | 
| options.wrapperProps | Object | - | Wrapper element other props | 
| options.defaultOverflow | boolean | - | Default value of overflow(returns) | 
| return | type | default | explain | 
|---|---|---|---|
| node | JSX.Elment | Render element | |
| overflow | boolean | false | Whether overflow content | 
| reObserveElement | function | Manual re-observe wrapper element | |
| recalculateEllipsis | function | Recalculate overflow content status | 
import { useEllipsis } from "@react-cmpt/hooks";
const Demo = ({ text }) => {
  const { node, overflow } = useEllipsis(text, { lineClamp: 2 });
  return overflow ? <Tooltip content={text}>{node}</Tooltip> : node;
};Browser compatibility
-webkit-line-clamp ResizeObserver API
Handle the setInterval timer function.
| option | type | default | explain | 
|---|---|---|---|
| fn | function | - | Handle function. (setInterval callback) | 
| delay | number | - | setInterval ms. | 
| options.autorun | boolean | true | Runs automatically when mounted | 
| return | type | default | explain | 
|---|---|---|---|
| state | idle,running | idle | Operating status. | 
| cancel | function | The clear timer function. | |
| run | function | Manual restart interval function. | 
import { useInterval } from "@react-cmpt/hooks";
const Demo = () => {
  const { state, cancel, run } = useInterval(() => {
    console.log("hi");
  }, 1000);
  // ...
};Check component mount state
| option | type | default | explain | 
|---|---|---|---|
| - | - | - | - | 
| return | type | default | explain | 
|---|---|---|---|
| callback | function | Get mount status | 
import { useMountedState } from "@react-cmpt/hooks";
const Demo = () => {
  const getMounted = useMountedState();
  useEffect(() => {
    setTimeout(() => {
      if (getMounted()) {
        // do...
      }
    }, 1000);
  }, []);
  // ...
};- check if safe-area-inset-[top]env is supported
- https://webkit.org/blog/7929/designing-websites-for-iphone-x/
| options | type | default | explain | 
|---|---|---|---|
| defaultState | boolean | - | default return bool | 
| position | 'top' | 'left' | 'right' | 'bottom' | top | safe-area-inset-[postion] | 
import { useLoadImg } from "@react-cmpt/hooks";
const Demo = () => {
  const supportSafeArea = useSupportSafeArea({ postion: "bottom" });
  return (
    <div
      style={{
        paddingBottom: supportSafeArea ? `env(safe-area-inset-bottom)` : "16px",
      }}
    >
      footer
    </div>
  );
};:root {
  @supports (top: constant(safe-area-inset-top)) {
    --safe-area-inset-top: constant(safe-area-inset-top);
    --safe-area-inset-right: constant(safe-area-inset-right);
    --safe-area-inset-bottom: constant(safe-area-inset-bottom);
    --safe-area-inset-left: constant(safe-area-inset-left);
  }
  @supports (top: env(safe-area-inset-top)) {
    --safe-area-inset-top: env(safe-area-inset-top);
    --safe-area-inset-right: env(safe-area-inset-right);
    --safe-area-inset-bottom: env(safe-area-inset-bottom);
    --safe-area-inset-left: env(safe-area-inset-left);
  }
}
.demo {
  padding-bottom: 16px;
  &[data-supportSafeArea="true"] {
    padding-bottom: var(--safe-area-inset-bottom);
  }
}Get image loading status
| option | type | default | explain | 
|---|---|---|---|
| src | string | <img />src | |
| reqLoading | boolean | request loading | |
| className | string | ||
| style | Object | ||
| imgProps | Object | <img />props | |
| lazy | number | 0 | Delay of done state | 
| return | type | default | explain | 
|---|---|---|---|
| imgNode | JSX.Element | <img /> | |
| state | loading,done,error,idle | idle | image state | 
| loading | boolean | ||
| isError | boolean | image errored | 
import { useLoadImg } from "@react-cmpt/hooks";
const Demo = () => {
  const { imgNode, loading } = useLoadImg({
    src: "[PATH]/demo.jpg",
    style: { width: "100%" },
  });
  return <div data-loading={loading}>{imgNode}</div>;
};throttled value
| option | type | default | explain | |
|---|---|---|---|---|
| value | any | - | The value to throttle. | |
| wait | number | 0 | The number of milliseconds to throttle invocations to. | |
| options | leading | boolean | - | Specify invoking on the leading edge of the timeout. | 
| customizer | function | - | The function to customize comparisons. | |
| return | type | explain | 
|---|---|---|
| value | any | Returns the new throttled value. | 
| cancel | function | The clear timer function. | 
| callPending | function | The callback manually function. | 
import { useThrottle } from "@react-cmpt/use-throttle";
const Demo = ({ value }) => {
  const [tValue, { cancel, callPending }] = useThrottle(value, 200);
  // ...
};throttled function
<
| option | type | default | explain | |
|---|---|---|---|---|
| fn | function | - | The function to throttle. | |
| wait | number | 0 | The number of milliseconds to throttle invocations to. | |
| options | leading | boolean | - | Specify invoking on the leading edge of the timeout. | 
| return | type | explain | 
|---|---|---|
| callback | function | The new throttled function. | 
| cancel | function | The clear timer function. | 
| callPending | function | The callback manually function. | 
import { useThrottleFn } from "@react-cmpt/use-throttle";
const Demo = () => {
  const { callback, cancel, callPending } = useThrottleFn(() => {
    console.log("click");
  }, 200);
  return <button onClick={callback}>++</button>;
};Unmount callback
| option | type | default | explain | 
|---|---|---|---|
| fn | function | 
import { useUnmount } from "@react-cmpt/hooks";
const Demo = () => {
  useUnmount(() => {
    console.log("Unmount");
  });
  // ...
};Re-render components
| return | type | default | explain | 
|---|---|---|---|
| rerender | function | rerender callback | 
import { useUpdate } from "@react-cmpt/hooks";
const Demo = () => {
  const rerender = useUpdate();
  return (
    <>
      <div>Date: {Date.now()}</div>
      <button onClick={rerender}>Update</button>
    </>
  );
};React.useEffect cancel the first mount trigger
| option | type | default | explain | 
|---|---|---|---|
| effect | function | Imperative function that can return a cleanup function | |
| deps | Array | If present, effect will only activate if the values in the list change. | 
import { useUpdateEffect, useDeepCompareCache } from "@react-cmpt/hooks";
const Demo = () => {
  useUpdateEffect(() => {
    console.log(value);
  }, [value]);
  // Deep comparison useUpdateEffect
  useUpdateEffect(() => {
    console.log(value);
  }, useDeepCompareCache([value]));
  // ...
};# build package
yarn build
# tests
yarn test
# lint
yarn lint