TypeError: Cannot read properties of null (reading 'useState') while testing component with react testing library

I'm learning testing on react and react components with react testing library and jest. While trying to test a component that works when rendering the component it works with no issue, but when testing it I get the Invalid hook error.

This is the Component.

import PropTypes from "prop-types";
import { useState } from "react";

export const CounterApp = ({ value }) => {
    const [counter, setCounter] = useState(value);

    function handleAdd() {
        setCounter(counter + 1);
    }
    function handleSubtract() {
        if (counter > 0) {
            setCounter(counter - 1);
        }
    }

    function handleReset() {
        setCounter(0);
    }
    return (
        <>
            <h1>CounterApp</h1>
            <h2> {counter} </h2>
            <button onClick={handleAdd}>+1</button>
            <button onClick={handleSubtract}>-1</button>
            <button onClick={handleReset}>Reset</button>
        </>
    );
};

CounterApp.propTypes = {
    value: PropTypes.number.isRequired,
};

This is the test I'm running

import { render } from "@testing-library/react";
import { CounterApp } from "../../src/components/CounterApp";

describe("<CounterApp /> Tests", () => {
    const initialValue = 10;

    test("should match the snapshot", () => {
        const { container } = render(<CounterApp value={initialValue} />);
        expect(container).toMatchSnapshot();
    });
});

And this is the error that I'm getting

 ● <CounterApp /> Tests › should match the snapshot                  
                                                                      
    TypeError: Cannot read properties of null (reading 'useState')    
                                                                      
      3 |                                                             
      4 | export const CounterApp = ({ value }) => {                  
    > 5 |       const [counter, setCounter] = useState(value);        
        |                                             ^
      6 |
      7 |       function handleAdd() {
      8 |               setCounter(counter + 1);

      at useState (node_modules/react/cjs/react.development.js:1622:21)
      at CounterApp (src/components/CounterApp.jsx:5:40)
      at renderWithHooks (../node_modules/react-dom/cjs/react-dom.development.js:16305:18)
      at mountIndeterminateComponent (../node_modules/react-dom/cjs/react-dom.development.js:20074:13)
      at beginWork (../node_modules/react-dom/cjs/react-dom.development.js:21587:16)
      at beginWork$1 (../node_modules/react-dom/cjs/react-dom.development.js:27426:14)
      at performUnitOfWork (../node_modules/react-dom/cjs/react-dom.development.js:26560:12)
      at workLoopSync (../node_modules/react-dom/cjs/react-dom.development.js:26466:5)
      at renderRootSync (../node_modules/react-dom/cjs/react-dom.development.js:26434:7)
      at recoverFromConcurrentError (../node_modules/react-dom/cjs/react-dom.development.js:25850:20)
      at performConcurrentWorkOnRoot (../node_modules/react-dom/cjs/react-dom.development.js:25750:22)
      at flushActQueue (../node_modules/react/cjs/react.development.js:2667:24)
      at act (../node_modules/react/cjs/react.development.js:2582:11) 
      at ../node_modules/@testing-library/react/dist/act-compat.js:63:25
      at renderRoot (../node_modules/@testing-library/react/dist/pure.js:159:26)
      at render (../node_modules/@testing-library/react/dist/pure.js:246:10)
      at Object.<anonymous> (test/components/CounterApp.test.jsx:8:31)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        2.194 s

Any advice will be really appreciate. Thanks in advance!

Upvotes: 12

Views: 10094

Answers (3)

viga11
viga11

Reputation: 71

Not specifically for this question, but if you are running into the same error message and by any chance you are instantiating a hook and sending it as a parameter of a component like this:

const myHook = useMyHook();
const container = render(
<Component
    useHook={myHook}
/>);

It will throw the same error, a hook must be instantiated inside a valid React component and not a test file, so you should mock the hook or use the renderHook() method from "@testing-library/react", like this:

const result = renderHook(() => useMyHook());
const container = render(
<Component
    useHook={result.current}
/>);

Upvotes: 1

dbyrne978
dbyrne978

Reputation: 66

I ran into this exact error myself because I had installed the testing frameworks in the outer directory of my project rather than the directory containing .babelrc, src/, components/, etc. If you run into this, it seems likely it will be a setup issue with what you have installed and where.

What I ran in my project directory: npm install --save-dev @testing-library/react @testing-library/jest-dom jest jest-environment-jsdom @babel/preset-env @babel/preset-react

Upvotes: 5

RinitaPuri
RinitaPuri

Reputation: 7

Perhaps in your state you need to initialize the initial value, which is the default?
For example,
const [counter, setCounter] = useState(0);
or
const [counter, setCounter] = useState(value || 0);

Upvotes: -3

Related Questions