問題
例えば、次のようなコンポーネントをStorybookに追加すると
import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { Toolbar as RebassToolbar, NavLink } from 'rebass';
import Logo from './Logo';
const Toolbar = styled(RebassToolbar)`
padding: 0 20px 0 20px;
`;
const NavLinks = styled.div`
margin: auto 12px;
`;
const Header = () => (
<Toolbar>
<Logo>Takus</Logo>
<NavLinks>
<NavLink to="/" is={Link} children="ホーム" />
<NavLink to="/posts" is={Link} children="一覧" />
</NavLinks>
</Toolbar>
);
export default Header;
import React from 'react';
import { storiesOf } from '@storybook/react';
import Header from './Header';
storiesOf('Header', module).add('default', () => <Header />);
次のようなエラーが発生する
You should not use <Link> outside a <Router>
react-routerのLinkをRouterでWrapされたコンポーネント外で使っているためにエラーが発生している
解決策
storiesOf
に生えている addDecorator
というAPIを使って、対象のコンポーネントを MemoryRouter
でWarpします。react-routerのドキュメントTestingにもある通り、テスト時にルータのコンテキストをスタブする用途で使われるようです。
import React from 'react';
import { MemoryRouter } from 'react-router'
import { storiesOf } from '@storybook/react';
import Header from './Header';
storiesOf('Header', module)
.addDecorator(story => (
<MemoryRouter initialEntries={['/', 'posts']}>{story()}</MemoryRouter>
))
.add('default', () => <Header />);
initialEntriesというプロパティには、対象のコンポーネントがLinkのto
で指定しているパスをダミーとして登録しておきます。
参考
https://github.com/storybooks/storybook/issues/769
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/MemoryRouter.md
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/testing.md