Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test react hooks state using Jest and React Hooks Library

I nav component then will toggle state in a sidebar as well as open and close a menu and then trying to get this pass in code coverage. When I log inside my test my state keeps showing up as undefined. Not sure how to tackle this one here.

Component.js:

const Navigation = (props) => {
  const {
    classes,
    ...navProps
  } = props;

  const [anchorEl, setanchorEl] = useState(null);
  const [sidebarOpen, setsidebarOpen] = useState(false);

  const toggleSidebar = () => {
    setsidebarOpen(!sidebarOpen);
  };

  const toggleMenuClose = () => {
    setanchorEl(null);
  };

  const toggleMenuOpen = (event) => {
    setanchorEl(event.currentTarget);
  };

  return (
    <Fragment>
     <Button
          onClick={toggleMenuOpen}
        />
      <SideMenu
        toggleSidebar={toggleSidebar}
      >
       <Menu
          onClose={toggleMenuClose}
        >
      </SideMenu>
    </Fragment>
  );
};

export default Navigation;

Test.js:

import { renderHook, act } from '@testing-library/react-hooks';

// Components
import Navigation from './navigation';

test('sidebar should be closed by default', () => {
    const newProps = {
        valid: true,
        classes: {}
    };

    const { result } = renderHook(() => Navigation({ ...newProps }));
    expect(result.current.sidebarOpen).toBeFalsy();
});
like image 718
user992731 Avatar asked Dec 19 '25 21:12

user992731


1 Answers

Author of react-hooks-testing-library here.

react-hooks-testing-library is not for testing components and interrogating the internal hook state to assert their values, but rather for testing custom react hooks and interacting withe the result of your hook to ensure it behaves how you expect. For example, if you wanted to extract a useMenuToggle hook that looked something like:

export function useMenuToggle() {
  const [anchorEl, setanchorEl] = useState(null);
  const [sidebarOpen, setsidebarOpen] = useState(false);

  const toggleSidebar = () => {
    setsidebarOpen(!sidebarOpen);
  };

  const toggleMenuClose = () => {
    setanchorEl(null);
  };

  const toggleMenuOpen = (event) => {
    setanchorEl(event.currentTarget);
  };

  return {
    sidebarOpen,
    toggleSidebar,
    toggleMenuClose,
    toggleMenuOpen
  }
}

Then you could test it with renderHook:

import { renderHook, act } from '@testing-library/react-hooks';

// Hooks
import { useMenuToggle } from './navigation';

test('sidebar should be closed by default', () => {
    const newProps = {
        valid: true,
        classes: {}
    };

    const { result } = renderHook(() => useMenuToggle());
    expect(result.current.sidebarOpen).toBeFalsy();

    act(() => {
        result.current.toggleSidebar()
    })

    expect(result.current.sidebarOpen).toBeTruthy();
});

Generally though, when a hook is only used by a single component and/or in a single context, we recommend you simply test the component and allow the hook to be tested through it.

For testing your Navigation component, you should take a look at react-testing-library instead.

import React from 'react';
import { render } from '@testing-library/react';

// Components
import Navigation from './navigation';

test('sidebar should be closed by default', () => {
    const newProps = {
        valid: true,
        classes: {}
    };

    const { getByText } = render(<Navigation {...newProps} />);
    
    // the rest of the test
});
like image 200
Michael Peyper Avatar answered Dec 21 '25 13:12

Michael Peyper



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!