前回、検索エンジン間の検索を楽にするツールをChrome拡張機能で開発しました。
現在はEditページを追加していたのですがRoutingで詰まってしまったのでメモに残しておきます。
(GIF画のようにショートカットキーでアプリを立ち上げると検索ページのキーワードを自動で取得してさらにショートカットキーを押すと検索してくれるアプリを作った)
Chromeストア
記事で仕様しているコードは上の拡張機能に使用しているコードです。
React Router
import { ChakraProvider } from '@chakra-ui/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import Layout from 'components/popup/template/Layout';
import PopUp from 'components/popup/PopUp';
import EditList from 'components/popup/page/EditList';
import { chakraGlobalTheme } from './styles/chakraGlobal';
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
import './styles/globalStyle.css';
import './styles/reset.css';
const App = () => {
return (
<ChakraProvider theme={chakraGlobalTheme}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Navigate to="/index.html" />} />
<Route path="index.html" element={<PopUp />} />
<Route path="/edit" element={<EditList />} />
</Route>
</Routes>
</BrowserRouter>
</ChakraProvider>
);
};
const container = document.getElementById('root')!;
const root = ReactDOM.createRoot(container);
root.render(<App />);
結論からいうと上のような形になりました。
<Route path="/" element={<Layout />}>
<Route index element={<Navigate to="/index.html" />} />
<Route path="/index.html" element={<PopUp />} />
<Route path="/edit" element={<EditList />} />
</Route>
chrome拡張機能のpopupに置いて、index.html(もしくは任意の名前のhtmlファイル)を最初に読み込む必要がありますので
<Route path="/" element={<Layout />}>のところの path を /index.html にしていたのですがこれだとポップアップを立ち上がらず。
そこで一旦は path="/" を通過させたのちに
<Route index element={<Navigate to="/index.html" />} />
を呼び出してリダイレクトさせる形を取りました。
<Route path="/index.html" element={<PopUp />} />
当然ながらPopup.tsxへ遷移します。
Layoutはどのようになっているのか
import React, { FC } from 'react';
import Header from 'components/popup/header/Header';
import Footer from 'components/popup/footer/Footer';
import { Outlet } from 'react-router-dom';
import { Box } from '@chakra-ui/react';
const Layout: FC = () => {
return (
<Box color="moji.main">
<Header />
<Outlet />
<Footer />
</Box>
);
};
export default Layout;
ヘッダーとフッターを読み込んでいますがその間に <Outlet />を読み込ませています。
これは react-router-dom v6 のコンポーネントで、いわゆる props.Component をより柔軟に呼び出せるようにしたものです。
Linkコンポーネントで飛ばす
import React, { FC } from 'react';
import { Box, Image, Flex, Text } from '@chakra-ui/react';
import BrandIcon100 from 'assets/Rapid-ReSearch-icon-100.png';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCog } from '@fortawesome/free-solid-svg-icons';
const Header: FC = () => {
return (
<header>
<Flex justify="center" alignItems="center" pt="8px">
<h1>Rapid Re-Search</h1>
<Box as="span" w="48px" h="48px" ml="8px">
<Image src={BrandIcon100} w="48px" h="48px" />
</Box>
<Link to={'/edit'}>
<Text color="#333">Edit</Text>
</Link>
<FontAwesomeIcon icon={faCog} />
</Flex>
</header>
);
};
export default Header;
あとはLinkコンポーネントで適当に飛ばしてあげるだけで動作を確認できました。
Chrome拡張機能においてReactは便利
最近のChromeストアを見ていてもリッチな拡張機能が増えてきている印象です。
教育コンテンツなどはサブスクを備えていたりアプリのようにリッチに作られていたりします。
最近ではNextJSによってSSRとSSGがメインとなってきた印象ですがSPAはChrome拡張機能においてまだ十分に役に立ちますね。