use-safe-force-update
Version:
React hook(s) for safely force-updating components
127 lines (115 loc) • 3.5 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
var react = require('react');
/**
* React hook for force-updating a component.
*
* @returns {function(): void}
* Function that forces an update of the component.
* @example
* ```jsx
* function Component() {
* const values = useRef({ number: 0 });
* const forceUpdate = useForceUpdate();
*
* const increaseNumber = useCallback(() => {
* values.current.number++;
* forceUpdate();
* }, [values, forceUpdate]);
*
* return (
* <>
* <label children={`Increase (currently ${values.current.number})`} for='bth' />
* <button onClick={increaseNumber} id='btn' />
* </>
* )
* }
* ```
*/
function useForceUpdate() {
return react.useReducer(function () {
}, undefined)[1];
}
/**
* React hook for force-updating a component only when mounted
* (and queuing an update for when the component is mounted.)
*
* @returns {function(): void}
* Function that attempts to force an update of the component. It also allows for queueing an update
* for when the component *has* been mounted, which is simply done by calling the function
* before the component has been mounted.
* @example <caption>Force-updates the component immediately after being mounted./caption>
* function Component() {
* const forceUpdate = useMountedForceUpdate();
*
* React.useMemo(() => {
* forceUpdate();
* }, []);
* }
*/
function useMountedForceUpdate() {
var forceUpdate = useForceUpdate();
var lifecycle = react.useRef({
queuedUpdate: false,
mounted: false,
unmounted: false
});
react.useEffect(function () {
lifecycle.current.mounted = true;
if (lifecycle.current.queuedUpdate) {
lifecycle.current.queuedUpdate = false;
forceUpdate();
}
return function () {
lifecycle.current.unmounted = true;
};
}, []);
return react.useCallback(function mountedForceUpdate() {
if (lifecycle.current.mounted) {
if (!lifecycle.current.unmounted) {
forceUpdate();
}
} else {
lifecycle.current.queuedUpdate = true;
}
}, [lifecycle, forceUpdate]);
}
/**
* React hook for force-updating a component only when it is mounted.
* _**Note:** For React 18+ users, this will not be any different from `useForceUpdate`, since
* there is no warning about `setState` on unmounted components._
*
* @returns {function(): void}
* Function that attempts to force an update of the component.
* @example <caption>Forces an update after 1-10 seconds, which React will never complain about.</caption>
* function Component() {
* const forceUpdate = useSafeForceUpdate();
*
* React.useMemo(() => {
* setTimeout(() => {
* forceUpdate() // React will not ever complain about this!
* }, [1000 + Math.random() * 9000])
* }, [])
* }
*/
function useSafeForceUpdate() {
var forceUpdate = useForceUpdate();
var lifecycle = react.useRef({
mounted: false,
unmounted: false
});
react.useEffect(function () {
lifecycle.current.mounted = true;
return function () {
lifecycle.current.unmounted = true;
};
}, []);
return react.useCallback(function safeForceUpdate() {
if (lifecycle.current.mounted && !lifecycle.current.unmounted) {
forceUpdate();
}
}, [lifecycle, forceUpdate]);
}
exports.useForceUpdate = useForceUpdate;
exports.useMountedForceUpdate = useMountedForceUpdate;
exports.useSafeForceUpdate = useSafeForceUpdate;
;