react用のコンポーネントの開発にstorybookを使っています。
そこでreacto-router-domとの連携を考慮して以下のようなコンポーネントを作りました。
storyboard上では以下のTagコンポーネントをテストするのに
<BrowserRouter><Tag></BrowserRouter>
という風にBrowserRouterの子要素のコンポーネントとして書かないと
エラーが出てしまわないように useRouter
フラグで <Link>
と<a>
を切り替えるような実装にしました。
typescript
1import * as React from 'react'; 2import { Link } from 'react-router-dom'; 3 4export interface TagProps { 5 name: string; 6 useRouter?: boolean; 7} 8 9const Tag = ({ name, useRouter }: TagProps) => { 10 11 if (useRouter) { 12 return ( 13 <Link className="level-item" to={`/tags/${name}`}> 14 <span className="tag is-primary">{name}</span> 15 </Link>); 16 } 17 return ( 18 <a className="level-item" href={`/tags/${name}`}> 19 <span className="tag is-primary">{name}</span> 20 </a>); 21};
ですが出来れば、<Tag>
自身が <BrowserRouter>
の子要素として設定されているかどうかを判定して
<Link>
と<a>
を切り替えるような挙動にしたいのです(一々useRouterフラグを使いたくない
)
恐らくcontext
を駆使してごちゃごちゃすればできそうな気もしますが、ちょっと触ったことがないですし、
そもそももっと簡単に記述する方法があるかもしれず質問させていただきました。
ちなみにもしstorybookでそのまま<Link>を使おうとすると以下のエラーが出ます
Invariant Violation: You should not use <Link> outside a <Router> at invariant (http://localhost:6006/static/preview.bundle.js:6918:15) at Link.render (http://localhost:6006/static/preview.bundle.js:52978:54) at finishClassComponent (http://localhost:6006/static/preview.bundle.js:42252:31) at updateClassComponent (http://localhost:6006/static/preview.bundle.js:42229:12) at beginWork (http://localhost:6006/static/preview.bundle.js:42608:16) at performUnitOfWork (http://localhost:6006/static/preview.bundle.js:44576:16) at workLoop (http://localhost:6006/static/preview.bundle.js:44685:28) at HTMLUnknownElement.callCallback (http://localhost:6006/static/preview.bundle.js:33302:14) at Object.invokeGuardedCallbackDev (http://localhost:6006/static/preview.bundle.js:33341:16) at invokeGuardedCallback (http://localhost:6006/static/preview.bundle.js:33198:27)
回答1件
あなたの回答
tips
プレビュー