use-callback-ref
Advanced tools
Comparing version 1.3.0 to 1.3.1
@@ -0,3 +1,5 @@ | ||
import * as React from 'react'; | ||
import { assignRef } from './assignRef'; | ||
import { useCallbackRef } from './useRef'; | ||
var currentValues = new WeakMap(); | ||
/** | ||
@@ -18,3 +20,26 @@ * Merges two or more refs together providing a single interface to set their value | ||
export function useMergeRefs(refs, defaultValue) { | ||
return useCallbackRef(defaultValue || null, function (newValue) { return refs.forEach(function (ref) { return assignRef(ref, newValue); }); }); | ||
var callbackRef = useCallbackRef(defaultValue || null, function (newValue) { | ||
return refs.forEach(function (ref) { return assignRef(ref, newValue); }); | ||
}); | ||
// handle refs changes - added or removed | ||
React.useLayoutEffect(function () { | ||
var oldValue = currentValues.get(callbackRef); | ||
if (oldValue) { | ||
var prevRefs_1 = new Set(oldValue); | ||
var nextRefs_1 = new Set(refs); | ||
var current_1 = callbackRef.current; | ||
prevRefs_1.forEach(function (ref) { | ||
if (!nextRefs_1.has(ref)) { | ||
assignRef(ref, null); | ||
} | ||
}); | ||
nextRefs_1.forEach(function (ref) { | ||
if (!prevRefs_1.has(ref)) { | ||
assignRef(ref, current_1); | ||
} | ||
}); | ||
} | ||
currentValues.set(callbackRef, refs); | ||
}, [refs]); | ||
return callbackRef; | ||
} |
@@ -0,3 +1,5 @@ | ||
import * as React from 'react'; | ||
import { assignRef } from './assignRef'; | ||
import { useCallbackRef } from './useRef'; | ||
const currentValues = new WeakMap(); | ||
/** | ||
@@ -18,3 +20,24 @@ * Merges two or more refs together providing a single interface to set their value | ||
export function useMergeRefs(refs, defaultValue) { | ||
return useCallbackRef(defaultValue || null, (newValue) => refs.forEach((ref) => assignRef(ref, newValue))); | ||
const callbackRef = useCallbackRef(defaultValue || null, (newValue) => refs.forEach((ref) => assignRef(ref, newValue))); | ||
// handle refs changes - added or removed | ||
React.useLayoutEffect(() => { | ||
const oldValue = currentValues.get(callbackRef); | ||
if (oldValue) { | ||
const prevRefs = new Set(oldValue); | ||
const nextRefs = new Set(refs); | ||
const current = callbackRef.current; | ||
prevRefs.forEach((ref) => { | ||
if (!nextRefs.has(ref)) { | ||
assignRef(ref, null); | ||
} | ||
}); | ||
nextRefs.forEach((ref) => { | ||
if (!prevRefs.has(ref)) { | ||
assignRef(ref, current); | ||
} | ||
}); | ||
} | ||
currentValues.set(callbackRef, refs); | ||
}, [refs]); | ||
return callbackRef; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.useMergeRefs = void 0; | ||
var tslib_1 = require("tslib"); | ||
var React = tslib_1.__importStar(require("react")); | ||
var assignRef_1 = require("./assignRef"); | ||
var useRef_1 = require("./useRef"); | ||
var currentValues = new WeakMap(); | ||
/** | ||
@@ -21,4 +24,27 @@ * Merges two or more refs together providing a single interface to set their value | ||
function useMergeRefs(refs, defaultValue) { | ||
return (0, useRef_1.useCallbackRef)(defaultValue || null, function (newValue) { return refs.forEach(function (ref) { return (0, assignRef_1.assignRef)(ref, newValue); }); }); | ||
var callbackRef = (0, useRef_1.useCallbackRef)(defaultValue || null, function (newValue) { | ||
return refs.forEach(function (ref) { return (0, assignRef_1.assignRef)(ref, newValue); }); | ||
}); | ||
// handle refs changes - added or removed | ||
React.useLayoutEffect(function () { | ||
var oldValue = currentValues.get(callbackRef); | ||
if (oldValue) { | ||
var prevRefs_1 = new Set(oldValue); | ||
var nextRefs_1 = new Set(refs); | ||
var current_1 = callbackRef.current; | ||
prevRefs_1.forEach(function (ref) { | ||
if (!nextRefs_1.has(ref)) { | ||
(0, assignRef_1.assignRef)(ref, null); | ||
} | ||
}); | ||
nextRefs_1.forEach(function (ref) { | ||
if (!prevRefs_1.has(ref)) { | ||
(0, assignRef_1.assignRef)(ref, current_1); | ||
} | ||
}); | ||
} | ||
currentValues.set(callbackRef, refs); | ||
}, [refs]); | ||
return callbackRef; | ||
} | ||
exports.useMergeRefs = useMergeRefs; |
{ | ||
"name": "use-callback-ref", | ||
"version": "1.3.0", | ||
"version": "1.3.1", | ||
"description": "The same useRef, but with callback", | ||
@@ -33,10 +33,11 @@ "main": "dist/es5/index.js", | ||
"devDependencies": { | ||
"@theuiteam/lib-builder": "^0.1.4", | ||
"@size-limit/preset-small-lib": "^2.1.6", | ||
"@types/enzyme-adapter-react-16": "^1.0.6", | ||
"enzyme-adapter-react-16": "^1.15.6" | ||
"@testing-library/jest-dom": "^6.1.5", | ||
"@testing-library/react": "^14.1.2", | ||
"@theuiteam/lib-builder": "^0.3.0", | ||
"jest-environment-jsdom": "^29.7.0" | ||
}, | ||
"peerDependencies": { | ||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0", | ||
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0" | ||
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", | ||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0" | ||
}, | ||
@@ -56,5 +57,6 @@ "peerDependenciesMeta": { | ||
"react", | ||
"hoot", | ||
"hook", | ||
"useRef", | ||
"createRef" | ||
"createRef", | ||
"merge refs" | ||
], | ||
@@ -61,0 +63,0 @@ "husky": { |
@@ -20,36 +20,44 @@ <div align="center"> | ||
> Keep in mind that useRef doesn't notify you when its content changes. | ||
Mutating the .current property doesn't cause a re-render. | ||
If you want to run some code when React attaches or detaches a ref to a DOM node, | ||
you may want to use ~~a callback ref instead~~ .... __useCallbackRef__ instead. | ||
> Mutating the .current property doesn't cause a re-render. | ||
> If you want to run some code when React attaches or detaches a ref to a DOM node, | ||
> you may want to use ~~a callback ref instead~~ .... **useCallbackRef** instead. | ||
– [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html#useref) | ||
Read more about `use-callback` pattern and use cases: | ||
Read more about `use-callback` pattern and use cases: | ||
- https://dev.to/thekashey/the-same-useref-but-it-will-callback-8bo | ||
This library exposes helpers to handle any case related to `ref` _lifecycle_ | ||
- `useCallbackRef` - react on hook change | ||
- `mergeRefs` - merge multiple refs together. For, actually, fork | ||
- `transformRef` - transform one ref to anther | ||
- `refToCallback` - convert RefObject to an old callback-style ref | ||
- `assignRef` - assign value to the ref, regardless of it's form | ||
- `useCallbackRef` - react on a ref change (replacement for `useRef`) | ||
- `createCallbackRef` - - low level version of `useCallbackRef` | ||
- `useMergeRefs` - merge multiple refs together creating a stable return ref | ||
- `mergeRefs` - low level version of `useMergeRefs` | ||
- `useTransformRef` - transform one ref to another (replacement for `useImperativeHandle`) | ||
- `transformRef` - low level version of `useTransformRef` | ||
- `useRefToCallback` - convert RefObject to an old callback-style ref | ||
- `refToCallback` - low level version of `useRefToCallback` | ||
- `assignRef` - assign value to the ref, regardless it is RefCallback or RefObject | ||
All functions are tree shakable, but even together it's __less then 300b__. | ||
All functions are tree shakable, but even together it's **less then 300b**. | ||
# API | ||
💡 Some commands are hooks based, and returns the same refs/functions every render. | ||
💡 Some commands are hooks based, and returns the same refs/functions every render. | ||
But some are not, to be used in classes or non-react code. | ||
## useRef API | ||
🤔 Use case: every time you have to react to ref change | ||
API is 99% compatible with React `createRef` and `useRef`, and just adds another argument - `callback`, | ||
which would be called on __ref update__. | ||
which would be called on **ref update**. | ||
#### createCallbackRef - to replace React.createRef | ||
- `createCallbackRef(callback)` - would call provided `callback` when ref is changed. | ||
- `createCallbackRef(callback)` - would call provided `callback` when ref is changed. | ||
#### useCallbackRef - to replace React.useRef | ||
- `useCallbackRef(initialValue, callback)` - would call provided `callback` when ref is changed. | ||
@@ -60,23 +68,24 @@ | ||
```js | ||
import {useRef, createRef, useState} from 'react'; | ||
import {useCallbackRef, createCallbackRef} from 'use-callback-ref'; | ||
import { useRef, createRef, useState } from 'react'; | ||
import { useCallbackRef, createCallbackRef } from 'use-callback-ref'; | ||
const Component = () => { | ||
const [,forceUpdate] = useState(); | ||
const [, forceUpdate] = useState(); | ||
// I dont need callback when ref changes | ||
const ref = useRef(null); | ||
const ref = useRef(null); | ||
// but sometimes - it could be what you need | ||
const anotherRef = useCallbackRef(null, () => forceUpdate()); | ||
useEffect( () => { | ||
useEffect(() => { | ||
// now it's just possible | ||
}, [anotherRef.current]) // react to dom node change | ||
} | ||
}, [anotherRef.current]); // react to dom node change | ||
}; | ||
``` | ||
💡 You can use `useCallbackRef` to convert RefObject into RefCallback, creating bridges between the old and the new code | ||
```js | ||
// some old component | ||
const onRefUpdate = (newValue) => {...} | ||
const onRefUpdate = (newRef) => {...} | ||
const refObject = useCallbackRef(null, onRefUpdate); | ||
@@ -88,2 +97,3 @@ // ... | ||
## assignRef | ||
🤔 Use case: every time you need to assign ref manually, and you dont know the shape of the ref | ||
@@ -98,7 +108,8 @@ | ||
import {assignRef} from "use-callback-ref"; | ||
✅ assignRef(ref, value); | ||
✅ assignRef(ref, value); | ||
``` | ||
## useTransformRef (to replace React.useImperativeHandle) | ||
🤔 Use case: ref could be different. | ||
🤔 Use case: ref could be different. | ||
`transformRef(ref, tranformer):Ref` - return a new `ref` which would propagate all changes to the provided `ref` with applied `transform` | ||
@@ -108,18 +119,18 @@ | ||
// before | ||
const ResizableWithRef = forwardRef((props, ref) => | ||
<Resizable {...props} ref={i => i && ref(i.resizable)}/> | ||
); | ||
const ResizableWithRef = forwardRef((props, ref) => <Resizable {...props} ref={(i) => i && ref(i.resizable)} />); | ||
// after | ||
const ResizableWithRef = forwardRef((props, ref) => | ||
<Resizable {...props} ref={transformRef(ref, i => i ? i.resizable : null)}/> | ||
); | ||
const ResizableWithRef = forwardRef((props, ref) => ( | ||
<Resizable {...props} ref={transformRef(ref, (i) => (i ? i.resizable : null))} /> | ||
)); | ||
``` | ||
## refToCallback | ||
`refToCallback(ref: RefObject): RefCallback` - for compatibility between the old and the new code. | ||
For the compatibility between `RefCallback` and RefObject use `useCallbackRef(undefined, callback)` | ||
For the compatibility between `RefCallback` and RefObject use `useCallbackRef(undefined, callback)` | ||
## useMergeRefs | ||
`mergeRefs(refs: arrayOfRefs, [defaultValue]):ReactMutableRef` - merges a few refs together | ||
@@ -130,4 +141,4 @@ | ||
```js | ||
import React from 'react' | ||
import {useMergeRefs} from 'use-callback-ref' | ||
import React from 'react'; | ||
import { useMergeRefs } from 'use-callback-ref'; | ||
@@ -138,4 +149,4 @@ const MergedComponent = React.forwardRef((props, ref) => { | ||
// both localRef and ref would be populated with the `ref` to a `div` | ||
return <div ref={useMergeRefs([localRef, ref])} /> | ||
}) | ||
return <div ref={useMergeRefs([localRef, ref])} />; | ||
}); | ||
``` | ||
@@ -145,3 +156,4 @@ | ||
## mergeRefs | ||
## mergeRefs | ||
`mergeRefs(refs: arrayOfRefs, [defaultValue]):ReactMutableRef` - merges a few refs together | ||
@@ -152,5 +164,6 @@ is a non-hook based version. Will produce the new `ref` every run, causing the old one to unmount, and be _populated_ with the `null` value. | ||
`mergeRefs` are "safe" to use as a part of other hooks-based commands, but don't forget - it returns a new object every call. | ||
`mergeRefs` are "safe" to use as a part of other hooks-based commands, but don't forget - it returns a new object every call. | ||
# Similar packages: | ||
- [apply-ref](https://github.com/mitchellhamilton/apply-ref) - `applyRefs` is simular to `mergeRef`, `applyRef` is similar to `assignRef` | ||
@@ -165,3 +178,3 @@ - [useForkRef](https://react-hooks.org/docs/use-fork-ref) - `useForkRef` is simular to `useMergeRefs`, but accepts only two arguments. | ||
# License | ||
MIT | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
51457
1173
171
5