I'm writing a test code with Jest for a custom hook in my web application.
It uses Recoil for state management, but the error message appears when I run npm run test
.
This is the error message.
This component must be used inside a <RecoilRoot> component.
16 | const useIds = () => {
17 | // const [ids, setIds] = React.useState([]);
> 18 | const [ids, setIds] = useRecoilState(idsState);
| ^
This is the test code.
import * as React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { useIds } from '@/hooks/useIds';
import { RecoilRoot } from 'recoil';
it('unit test for custom hook useIds', () => {
const TestComponent: React.FC = () => {
const ids = useIds();
return (
<RecoilRoot>
<div title='ids'>{ ids }</div>
</RecoilRoot>
)
}
const { getByTitle } = render(<TestComponent />);
const ids = getByTitle('ids');
})
This is the custom hook code
import * as React from 'react';
import { useRouter } from 'next/router';
import { atom, useRecoilState } from 'recoil';
import { fetchIdsByType } from '@/repositories';
const initialState: {
[type: string]: number[];
} = {};
export const idsState = atom({
key: 'idsState',
default: initialState,
});
const useIds = () => {
const [ids, setIds] = useRecoilState(idsState);
const router = useRouter();
const { type } = router.query;
React.useEffect(() => {
if (router.asPath !== router.route) {
// @ts-ignore
fetchIdsByType(type).then((ids: number[]) => {
setIds((prevState) => {
return {
...prevState,
// @ts-ignore
[type]: ids,
};
});
});
}
}, [router]);
// @ts-ignore
return ids[type];
};
export { useIds };
I know why the error is happening but I have no idea where the RecoilRoot
should be in?
You might need to put where to wrap the component which is using your custom hook as following:
it('unit test for custom hook useIds', () => {
const TestComponent: React.FC = () => {
const ids = useIds();
return (
<div title='ids'>{ ids }</div>
)
}
const { getByTitle } = render(
// Put it here to wrap your custom hook
<RecoilRoot>
<TestComponent />
</RecoilRoot>
);
const ids = getByTitle('ids');
})