Zero-dependencies library for React
to store and access multiple references to child components.
See Example of usage section for an example when this library can be helpful.
npm install --save react-refs-collection
import useRefsCollection from 'react-refs-collection';
// Some functional component that renders multiple children and
// should be able to call imperative handlers on them:
const ItemsList = ({items}) => {
const {getRefHandler, getRef} = useRefsCollection();
const doSomeActionOnItem = useCallback(itemId => {
getRef(itemId).doSomeAction();
}, []);
return (
<div>
{items.map(({id, ...restProps}) => (
<Item
ref={getRefHandler(id)}
{...restProps}
/>
))}
</div>
)
}
For example we have the following UI:
- Search input + submit button
- List of some items
When user filled search input and submitted it - we have to scroll list of items to first item that matches given search criteria and focus this item.
Here is an implementation (Live Demo):
import useRefsCollection from 'react-refs-collection';
const MyComponent = (items) => {
const {getRefHandler, getRef} = useRefsCollection();
const [searchValue, setSearchValue] = useState("");
const onChange = useCallback(e => {
setSearchValue(e.target.value);
}, []);
const searchItem = useCallback(() => {
const match = items.find(item =>
item.value.toLowerCase().startsWith(searchValue.toLowerCase())
);
if (!match) return;
const itemNode = getRef(match.id);
if (itemNode) {
itemNode.focus();
}
}, [getRef, searchValue]);
// Search value when user pressed "Enter":
const onInputKeyUp = useCallback(
e => {
if (e.keyCode === 13) {
searchItem();
}
},
[searchItem]
);
return (
<div>
<div>
<input
type="text"
value={searchValue}
onChange={onChange}
onKeyUp={onInputKeyUp}
/>
<button onClick={searchItem}>Search</button>
</div>
<div>
{items.map(item => (
<div
key={item.id}
className="focusable"
ref={getRefHandler(item.id)}
tabIndex={-1}
>
{item.value}
</div>
))}
</div>
</div>
);
}
const items = [
{id: 1, content: 'One'},
{id: 2, content: 'Two'},
{id: 3, content: 'Three'},
{id: 4, content: 'Four'},
{id: 5, content: 'Five'},
{id: 6, content: 'Six'},
{id: 7, content: 'Seven'},
{id: 8, content: 'Eight'},
{id: 9, content: 'Nine'},
{id: 10, content: 'Ten'}
]
ReactDOM.render(<MyComponent items={items} />, document.getElementById('app'));
useRefsCollection
hook returns the following:
method | description |
---|---|
getRefHandler(key) | returns value that should be passed to "ref" property of some react component to store reference to this component in collection under given key |
getRef(key) | Returns reference by it's key |
getKeysByRef(ref) | Returns array of all keys that relates to given reference object (or empty array if there is no keys assigned to given reference object) |
getKeyByRef(ref) | Same as getKeysByRef, but returns only first found key or undefined if there is no key found. |