React Hooks ref.current не определен во время теста

#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 имеет некоторое значение, прежде чем переходить к вашему пользовательскому хуку.