Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError with Vitest: Cannot read properties of null (reading 'useRef')

I am trying to set up testing for my React app using Vitest, but I am experiencing an error which must be due to some missing dependency or error in my test suite. I'm unsure what exactly is the cause. When I try to run my tests I get the following error:

TypeError: Cannot read properties of null (reading 'useRef')

It says it's happening in my Login component, which contains a hook from react-hook-form.

export default function Login() {

    const { register, handleSubmit } = useForm();
                                       ^ 

When I remove this apparently problematic line it causes a similar problem elsewhere, where it says that an instance of useReducer is null.

This is what my setupTests.js looks like:

import { server } from './mocks/server';
import '@testing-library/jest-dom';

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Here is my Vite config:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [react()],
    test: {
        globals: true,
        environment: 'jsdom',
        setupFiles: './src/setupTests.js',
    }
})

And here is my package.json:

  {
  "name": "my-project",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "knex": "knex",
    "test": "vitest"
  },
  "dependencies": {
    "bcrypt": "^5.0.1",
    "cloudinary": "^1.30.0",
    "connect-session-knex": "^3.0.0",
    "cors": "^2.8.5",
    "dotenv": "^16.0.1",
    "express": "^4.18.1",
    "express-session": "^1.17.3",
    "knex": "^2.0.0",
    "multer": "^1.4.5-lts.1",
    "passport": "^0.5.3",
    "passport-local": "^1.0.0",
    "pg": "^8.7.3",
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "react-hook-form": "^7.31.2",
    "react-router-dom": "^6.3.0",
    "sass": "^1.51.0",
    "vitest": "^0.16.0"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^14.2.1",
    "@types/react": "^18.0.0",
    "@types/react-dom": "^18.0.0",
    "@vitejs/plugin-react": "^1.3.0",
    "jsdom": "^20.0.0",
    "msw": "^0.42.3",
    "vite": "^2.9.9"
  }
}

All these hooks work perfectly fine outside of the tests, so I am not sure why they are undefined.

I tried installing @testing-library/react-hooks in the hope that it might fix my problem but I was unable to do so as it doesn't appear to support React 18.

I'd really appreciate your support.

like image 894
A-PSquestions Avatar asked Oct 18 '25 17:10

A-PSquestions


2 Answers

I had the exact same problem so I investigated a bit and I figured out a working solution.

Working solution with @testing-library/react > 13.1

Use renderHook method from @testing-library/react package and wrap your hooks with it:

import React from 'react';
import { render, renderHook, screen } from '@testing-library/react'; 
import { describe, test } from 'vitest';
import { FormProvider, useForm } from 'react-hook-form';

describe('Input', () => {
  test('should render an Input component', () => {
    type FormValues = {
      field: string;
    };

    const { result } = renderHook(
      () => useForm<FormValues>({
        defaultValues: {
          field: '',
        },
      })
    );
    const methods = result.current;
    const { register } = methods;

    render(
      <FormProvider {...methods}>
        <form>
          <input {...register('field')} data-testid="my-field" />
        </form>
      </FormProvider>
    );

    expect(screen.getByTestId('my-field').toHaveAttribute('name', 'field'));
  });
});

In details

First of all, the reason why the hooks are not working is because we are in a testing context so the functions we are using need to be mocked.
@testing-library provides a solution to being able to use the hooks. Since @testing-library/react@^13.1, the package @testing-library/react-hooks is useless as you can read here: https://www.npmjs.com/package/@testing-library/react-hooks#user-content-a-note-about-react-18-support

Let's say that we have a test like this using React Hook Form and Vitest:

import React from 'react';
import { describe, test } from 'vitest';
import { FormProvider, useForm } from 'react-hook-form';

describe('Input', () => {
  test('should render an Input component', () => {
    type FormValues = {
      field: string;
    };

    const methods = useForm<FormValues>({ defaultValues: { field: '' } }); 
    const { register } = methods;

    render(
      <FormProvider {...methods}>
        <form>
          <input {...register('field')} data-testid="my-field" />
        </form>
      </FormProvider>
    );

    expect(screen.getByTestId('my-field').toHaveAttribute('name', 'field'));
  });
});

This test will crash with the following error:

TypeError: Cannot read properties of null (reading 'useRef')

To make it work, add this import:

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

And replace the previous useForm React Hook Form hook by:

const { result } = renderHook(
  () => useForm<FormValues>({
    defaultValues: {
      field: ''
    },
  })
);
const methods = result.current;

And now the test is working well 🥳

Before @testing-library/react@^13.1

Run the following command to add @testing-library/react-hooks to your project:

npm i --save-dev @testing-library/react-hooks

And import renderHook from the package you just installed

import { renderHook } from '@testing-library/react-hooks`

The documentation can be found here: https://www.npmjs.com/package/@testing-library/react-hooks#table-of-contents

like image 181
Fabien Essid Avatar answered Oct 20 '25 06:10

Fabien Essid


This went away for me when I added the react plugin

import react from '@vitejs/plugin-react';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  plugins: [react()],
});

like image 32
Mark Swardstrom Avatar answered Oct 20 '25 07:10

Mark Swardstrom



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!