#javascript #reactjs #unit-testing #jestjs #react-hooks
#javascript #reactjs #модульное тестирование #jestjs #реагирующие крючки
Вопрос:
TLDR — У меня есть отзывчивый компонент, использующий ref.current.offsetWidth, но он не работает, когда я тестирую его с помощью Jest
Компонент navbar работает и отлично отображается на localhost. Но когда я пытаюсь стимулировать разную ширину экрана, используя Jest для модульного тестирования, перехват ref по какой-то причине не может определить длину div. Есть предложения о том, как это исправить?
Ошибка: TypeError: Cannot read property 'offsetWidth' of undefined
Код: Navbar.js
// custom hook to get live div width
const useContainerDimensions = myRef => {
const getDimensions = () => ({
width: myRef.current.offsetWidth, //location of error
});
const [dimensions, setDimensions] = useState({ width: 0 });
useEffect(() => {
const handleResize = () => {
setDimensions(getDimensions());
};
if (myRef.current) {
setDimensions(getDimensions());
}
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, [myRef]);
return dimensions;
};
const Navbar = () => {
const inputRef = useRef();
const { width } = useContainerDimensions(inputRef);
useEffect(() => {
if (width >= 890) {
setCurrTabPerRow(5);
setTabStyle('5 tabs');
}
if (width < 890) {
setCurrTabPerRow(4);
setTabStyle('4 tabs');
}
}, [width]);
return (
...
<div ref={inputRef}>
//...stuff
</div>
...
)
}
export default Navbar;
navbar.test.js
const resizeWindow = (x, y) => {
window.innerWidth = x;
window.innerHeight = y;
window.dispatchEvent(new Event('resize'));
}
describe('Navbar component', () => {
it('should render', () => {
const component = mount(
<Navbar filter>
<Navbar.Tab id="stuff1" />
<Navbar.Tab id="stuff2" />
<Navbar.Tab id="stuff3" />
</Navbar>
);
act(() => {
resizeWindow(500, 300);
});
expect(component).toMatchSnapshot();
});
});
Ответ №1:
Начальное значение ref не определено. Вы можете просто проверить, что myRef.current
существует, прежде чем обращаться к дальнейшим свойствам. и укажите резервное значение.
const getDimensions = () => ({
width: (myRef.current amp;amp; myRef.current.offsetWidth) || 0,
});
или с необязательной цепочкой
const getDimensions = () => ({
width: myRef?.current?.offsetWidth || 0,
});
Ответ №2:
Перехват useRef изначально не имеет значения. Вы передаете inputRef
сразу после его объявления.
Попробуйте сделать что-то вроде этого:
const [containerWidth, setContainerWidth] = useState(0);
useEffect(() => {
if(inputRef.current) {
const { width } = useContainerDimensions(inputRef);
setContainerWidth(width);
}
}, [inputRef])
Затем вы убедитесь, что inputRef
имеет некоторое значение, прежде чем переходить к вашему пользовательскому хуку.