useResize
Hook that provides ability to listen element resizing.
import { useRef } from 'react';
import { useResize } from '@krutoo/utils/react';
function App() {
const ref = useRef<HTMLDivElement>(null);
useResize(ref, entry => {
console.log('Actual size is', entry.borderBoxSize);
});
return <div ref={ref}></div>;
}
ResizeObserverContext
Under the hood this hook uses ResizeObserverContext to create observer.
ResizeObserverContext by default uses global window.ResizeObserver.
But using global instance trough context gives you ability to replace implementation whenever you want.
It means that you can:
- provide polyfill implementation for environments that don't support
ResizeObserver; - provide implementation for SSR;
- provide different implementations for different subtrees of your UI;
- replace instance by mock in your unit tests.
For example next we will use ResizeObserverMock:
import { useRef, useState } from 'react';
import { ResizeObserverContext, useResize } from '@krutoo/utils/react';
import { ResizeObserverMock } from '@krutoo/utils/testing';
import { act, expect, render, test } from '#testing';
function MyWidget() {
const [wide, setWide] = useState(false);
const ref = useRef(null);
useResize(ref, entry => {
const size = entry.borderBoxSize[0]?.inlineSize ?? 0;
setWide(size >= 720);
});
return (
<div ref={ref} className='my-widget'>
{wide ? 'I am wide' : 'I am thin'}
</div>
);
}
test('MyWidget should render message about width', () => {
let observer;
const context = {
getObserver(...args) {
observer = new ResizeObserverMock(...args);
return observer;
},
};
const { container } = render(
<ResizeObserverContext value={context}>
<MyWidget />
</ResizeObserverContext>,
);
expect(container.textContent).toBe('I am thin');
act(() => {
observer.simulateResize([
{
target: document.querySelector('.my-widget'),
borderBoxSize: [{ inlineSize: 800, blockSize: 100 }],
},
]);
});
expect(container.textContent).toBe('I am wide');
});
This example shows that you don't need to use environment that implements ResizeObserver during testing.
So you can use jsdom for example.