概要
StorybookでReact RouterのLinkを使用しているコンポーネントを表示したところ、以下のエラーが発生しました。
Cannot destructure property 'basename' of 'import_react.useContext(...)' as it is null.
やりたいこと
React RouterのLinkを使用しているコンポーネントのStoryを表示したい。
実行したコード
preview.tsx
import type { Preview } from "@storybook/react-vite";
import { MemoryRouter } from "storybook/internal/router";
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
a11y: {
test: "todo",
},
},
tags: ["autodocs"],
decorators: [
(Story) => (
<MemoryRouter>
<Story />
</MemoryRouter>
),
],
};
export default preview;
表示するコンポーネントでは、React RouterのLinkを使用しています。
import { Link } from "react-router";
export const Links = () => {
return (
<ul>
<li>
<Link to="/sample">サンプル</Link>
</li>
</ul>
);
};
Interaction Testでは、リンクが表示されることを確認しています。
await step("リンクが表示される", async () => {
const expected = ["サンプル"];
for (let index = 0; index < listItems.length; index++) {
await expect(
within(listItems[index]).getByRole("link", {
name: expected[index],
}),
).toBeVisible();
}
});
エラー内容
Cannot destructure property 'basename' of 'import_react.useContext(...)' as it is null.
原因調査
エラーについて検索しました。
調べると、MemoryRouterで囲っていないことが原因という情報が出てきました。
しかし、preview.tsxではすでにMemoryRouterで囲っていました。
<MemoryRouter>
<Story />
</MemoryRouter>
そこでMemoryRouterのimport元を確認しました。
原因
MemoryRouterをStorybook内部のモジュールからimportしていたことが原因でした。
import { MemoryRouter } from "storybook/internal/router";
解決策
MemoryRouterをreact-routerからimportするように変更しました。
import { MemoryRouter } from "react-router";
参考