最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Hooks ref.current is undefined during test - Stack Overflow

programmeradmin7浏览0评论

TLDR - I have a responsive ponent using ref.current.offsetWidth but it doesn't work when I test it with Jest

The navbar ponent works and renders fine in localhost. But when I'm trying to stimulate different screen widths using Jest for unit testing, the ref hook is unable to pick up div length for some reason. Any suggestion on how to fix this?

Error: TypeError: Cannot read property 'offsetWidth' of undefined

Code: 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 ponent', () => {
  it('should render', () => {
    const ponent = mount(
      <Navbar filter>
        <Navbar.Tab id="stuff1" />
        <Navbar.Tab id="stuff2" />
        <Navbar.Tab id="stuff3" />
      </Navbar>
    );
    act(() => {
      resizeWindow(500, 300);
    });
    expect(ponent).toMatchSnapshot();
  });
});

TLDR - I have a responsive ponent using ref.current.offsetWidth but it doesn't work when I test it with Jest

The navbar ponent works and renders fine in localhost. But when I'm trying to stimulate different screen widths using Jest for unit testing, the ref hook is unable to pick up div length for some reason. Any suggestion on how to fix this?

Error: TypeError: Cannot read property 'offsetWidth' of undefined

Code: 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 ponent', () => {
  it('should render', () => {
    const ponent = mount(
      <Navbar filter>
        <Navbar.Tab id="stuff1" />
        <Navbar.Tab id="stuff2" />
        <Navbar.Tab id="stuff3" />
      </Navbar>
    );
    act(() => {
      resizeWindow(500, 300);
    });
    expect(ponent).toMatchSnapshot();
  });
});
Share Improve this question edited Aug 21, 2020 at 21:44 Drew Reese 204k18 gold badges245 silver badges273 bronze badges asked Aug 21, 2020 at 21:29 Jpark9061Jpark9061 1,1304 gold badges16 silver badges36 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

The initial value of the ref is undefined. You can simply check that the myRef.current exists before accessing further properties. and provide a fallback value.

const getDimensions = () => ({
  width: (myRef.current && myRef.current.offsetWidth) || 0,
});

or with optional chaining

const getDimensions = () => ({
  width: myRef?.current?.offsetWidth || 0,
});

The useRef hook initially has no value. You're passing the inputRef right after declaring it.

Try to do something like this:

const [containerWidth, setContainerWidth] = useState(0);

useEffect(() => {
  if(inputRef.current) {
    const { width } = useContainerDimensions(inputRef);

    setContainerWidth(width);
  }
}, [inputRef])

Then you make sure that the inputRef has some value before passing to your custom hook.

发布评论

评论列表(0)

  1. 暂无评论