It's React's useEffect/useMemo/useCallback hooks, except using custom comparison on the inputs, not reference equality
npm install use-custom-compare
# or
yarn add use-custom-compare
import React from "react";
import { useCustomCompareEffect } from "use-custom-compare";
import isEqual from "lodash/isEqual";
function App({ options }) {
useCustomCompareEffect(
() => {
// do something significant here
return () => {
// return to clean up that significant thing
};
},
[options],
(prevDeps, nextDeps) => isEqual(prevDeps, nextDeps)
);
return <div>{/* render significant thing */}</div>;
}
import React from "react";
import { useCustomCompareLayoutEffect } from "use-custom-compare";
import isEqual from "lodash/isEqual";
function App({ options }) {
useCustomCompareLayoutEffect(
() => {
// do something significant here
return () => {
// return to clean up that significant thing
};
},
[options],
(prevDeps, nextDeps) => isEqual(prevDeps, nextDeps)
);
return <div>{/* render significant thing */}</div>;
}
import React from "react";
import { useCustomCompareMemo } from "use-custom-compare";
import isEqual from "lodash/isEqual";
function App({ options }) {
const memoized = useCustomCompareMemo(
() => {
// do something significant here
},
[options],
(prevDeps, nextDeps) => isEqual(prevDeps, nextDeps)
);
return <div>{/* render significant thing */}</div>;
}
import React from "react";
import { useCustomCompareCallback } from "use-custom-compare";
import isEqual from "lodash/isEqual";
function App({ options }) {
const memoized = useCustomCompareCallback(
() => {
// do something significant here
},
[options],
(prevDeps, nextDeps) => isEqual(prevDeps, nextDeps)
);
return <div>{/* render significant thing */}</div>;
}
This custom compare hooks is type-safe because it is built with TypeScript, which requires the use of TypeScript 4.0 or higher.
import React from "react";
import { useCustomCompareEffect } from "use-custom-compare";
import isEqual from "lodash/isEqual";
function App() {
useCustomCompareEffect(
() => {},
[1, { a: "b" }, true],
(
prevDeps, // type: readonly [number, { a: string }, boolean]
nextDeps // type: readonly [number, { a: string }, boolean]
) => isEqual(prevDeps, nextDeps)
);
return <div />;
}
exhaustive-deps
in eslint-plugin-react-hooks can be configured to validate dependencies.
If you want to apply that rule to this custom compare hooks as well, use the additionalHooks
option.
{
"rules": {
// ...
"react-hooks/exhaustive-deps": [
"warn",
{
additionalHooks:
"(useCustomCompareEffect|useCustomCompareLayoutEffect|useCustomCompareMemo|useCustomCompareCallback)"
}
]
}
}
In the following cases, use React's useEffect/useMemo/useCallback hooks instead of this custom compare hooks!
- no dependencies
- dependencies are all primitive values
Contributions are always welcome! Please read the contributing first.
use-deep-compare-effect
π It's react's useEffect hook, except using deep comparison on the inputs, not reference equality.use-deep-compare
It's react's useEffect/useMemo/useCallback hooks, except using deep comparison on the inputs.use-custom-compare-effect
useEffect hook which takes a comparison function instead of compare using reference equality.
Thanks goes to these wonderful people (emoji key):
Kotaro Sugawara π» π π€ π |
This project follows the all-contributors specification. Contributions of any kind welcome!