React Router: v5 からの更新
アプリ内のReact Routerをv5からv6にアップデートした時のメモです.
デモアプリは here です.
v6 では Switch の代わりに Routes を使用し、exact キーワードは必要ありません.また、 element は Route ページ内のコンポーネントを割り当てるための新しい属性です.
ちょっとした発見として、レイアウト コンポーネントをルート内に配置することは不可能です.そのため、各ページ コンポーネントをそれぞれレイアウトでラップする必要があります.さらに、「*」は、パスに少なくとも 1 つの子パスがあることを Router に知らせるために重要です.
**リファクタリング
Routes でのパターンの繰り返しを避けるために、WithLayout コンポーネントとラップされたページ コンポーネントを追加しました.
レイアウトあり
家
私の本
見つかりません
アプリ
v5 では絶対パスを使用する必要がありましたが、子パスを追加するときは相対パスを使用してください.
公式ドキュメントによると、useMatch は useRouteMatch の代替です.ただし、useRouteMatch の使用方法によっては、useLocation を代替することができます.私の場合、以前のパスを知るために useRouteMatch を使用しました.これは、useLocation が代替ソリューションになる場合です.
useHistory は使用できなくなりました.前のページから別のページに移動する場合は、代わりに useNavigate を使用してください.
置き換えたいときに指定するオブジェクトを配置します.
activeClassName が削除されたため、代わりに isActive を使用して、特定のナビゲーションがアクティブかどうかを認識する必要があります.
Redirect は使っていませんが、Redirect の削除も v5 からの大きな変更点だと思います.代替コンポーネントはナビゲートですが、属性が少し変更されています. Redirect では、replace がデフォルトであり、必要に応じて push を使用しました.一方、Navigate では push がデフォルトであり、replace を使用する必要があります.
the official document からより詳細な情報を見つけることができます.
このアップデートの私の印象は、v6 でネストされたパスを処理しやすくなったということです.また、要素を使用するため、ページ コンポーネントとその他のコンポーネントを分離することがより重要になります.これにより、コーディングがよりクリーンになると思います.ただし、activeClassName の削除は、私にとっては少し不便です.
読んでくれてありがとう :)
元の記事は here です
デモアプリは here です.
スイッチ -> ルート
v6 では Switch の代わりに Routes を使用し、exact キーワードは必要ありません.また、 element は Route ページ内のコンポーネントを割り当てるための新しい属性です.
v5
<Switch>
<Route path="/" exact>
<LaunchPage />
</Route>
<Layout>
<Switch>
<Route path="/search-book">
<Home />
</Route>
<Route path="/my-books">
<MyBooks />
</Route>
</Switch>
</Layout>
</Switch>
v6
ちょっとした発見として、レイアウト コンポーネントをルート内に配置することは不可能です.そのため、各ページ コンポーネントをそれぞれレイアウトでラップする必要があります.さらに、「*」は、パスに少なくとも 1 つの子パスがあることを Router に知らせるために重要です.
<Routes>
<Route path="/" element={<LaunchPage />} />
<Route path="search-book/" element={<Layout><Home /></Layout>} />
<Route path="my-books" element={<Layout><MyBooks /></Layout>}/></Routes>
**リファクタリング
Routes でのパターンの繰り返しを避けるために、WithLayout コンポーネントとラップされたページ コンポーネントを追加しました.
レイアウトあり
import Layout from "../Layout/Layout.jsx";
function WithLayout(Child) {
return function WithLayout(props) {
return (
<Layout>
<Child {...props} />
</Layout>
);
};
}
export default WithLayout;
家
import SearchBooks from "../components/SearchBooks";
import WithLayout from "../hoc/WithLayout";
const Home = () => {
return <SearchBooks />;
};
export default **WithLayout(Home)**;
私の本
import { Fragment, useContext } from "react";
import MyBookItem from "../components/MyBookItem";
import SortMyBooks from "../components/SortMyBooks";
import MyBooksContext from "../store/my-books-context";
import classes from "./MyBooks.module.css";
import WithLayout from "../hoc/WithLayout";
// functions
const MyBooks = () => {
// functions
return (
<Fragment>
<SortMyBooks
onTitle={sortByTitleHandler}
onDate={sortByDateHandler}
onRating={sortByRatingHandler}
onDefault={defaultHandler}
/>
<div className={classes.box}>
{myBooksCtx.myBooks.length !== 0 && content}
{myBooksCtx.myBooks.length === 0 && (
<p>No books here yet. Let's add your book!</p>
)}
</div>
</Fragment>
);
};
export default **WithLayout(MyBooks)**;
見つかりません
import React from "react";
import { Link } from "react-router-dom";
import classes from "./NotFound.module.css";
import WithLayout from "../hoc/WithLayout";
function NotFound() {
return (
<div className={classes["not-found"]}>
<h1>404</h1>
<h2>Page Not Found </h2>
<p>
Back to <Link to="/search-book">Home</Link>
</p>
</div>
);
}
export default WithLayout(NotFound);
アプリ
import React, { Fragment, Suspense } from "react";
import { Route, Routes } from "react-router-dom";
import LaunchPage from "./pages/LaunchPage";
import Home from "./pages/Home";
import LoadingSpinner from "./UI/LoadingSpinner";
import NotFound from "./pages/NotFound";
const MyBooks = React.lazy(() => import("./pages/MyBooks"));
function App() {
return (
<Fragment>
<Suspense
fallback={
<div className="centered">
<LoadingSpinner />
</div>
}
>
<Routes>
<Route path="/" element={<LaunchPage />} />
<Route path="search-book/*" element={<Home />} />
<Route path="my-books" element={<MyBooks />} />
<Route path="*" element={<NotFound />} />
</Routes>
</Suspense>
</Fragment>
);
}
export default App;
フルパス -> 相対パス
v5 では絶対パスを使用する必要がありましたが、子パスを追加するときは相対パスを使用してください.
v5
<Route path={match.url} exact>
//*elements*
</Route>
<Route path={`${match.url}/add-my-books`}>
<AddMyBooks />
</Route>
v6
<Routes>
<Route path="" element={
<BookDetailComponent path={location.pathname} />
}/>
<Route path="add-my-books" element={<AddMyBooks />} />
</Routes>
useRouteMatch -> useLocation
公式ドキュメントによると、useMatch は useRouteMatch の代替です.ただし、useRouteMatch の使用方法によっては、useLocation を代替することができます.私の場合、以前のパスを知るために useRouteMatch を使用しました.これは、useLocation が代替ソリューションになる場合です.
v5
const BookItem = (props) => {
const itemCtx = useContext(ItemContext);
const match = useRouteMatch();
const updateItemHandler = () => {
itemCtx.updateItem(props.item);
};
return (
<Fragment>
<Link
className={classes.box}
to={`${match.path}/${props.item.id}`}
onClick={updateItemHandler}
>
<img
className={classes.image}
src={props.item.image ? props.item.image : noImage}
alt={props.item.title}
></img>
</Link>
</Fragment>
);
};
v6
const BookItem = (props) => {
const itemCtx = useContext(ItemContext);
const location = useLocation();
const updateItemHandler = () => {
itemCtx.updateItem(props.item);
};
return (
<Fragment>
<Link
className={classes.box}
to={`${location.pathname}/${props.item.id}`}
onClick={updateItemHandler}
>
<img
className={classes.image}
src={props.item.image ? props.item.image : noImage}
alt={props.item.title}
></img>
</Link>
</Fragment>
);
};
useHistory -> useNavigate
useHistory は使用できなくなりました.前のページから別のページに移動する場合は、代わりに useNavigate を使用してください.
v5
const history = useHistory();
const submitHandler = (event) => {
event.preventDefault();
const formattedDate = formatDate(inputDate);
const mybook = {
id: "" + inputDate.getTime() + itemCtx.item.id,
date: formattedDate,
rating,
title: itemCtx.item.title,
authors: itemCtx.item.authors,
image: itemCtx.item.image,
comment,
};
myBooksCtx.updateMyBooks(mybook);
history.replace("/my-books");
};
v6
置き換えたいときに指定するオブジェクトを配置します.
const navigate = useNavigate();
const submitHandler = (event) => {
event.preventDefault();
const formattedDate = formatDate(inputDate);
const mybook = {
id: "" + inputDate.getTime() + itemCtx.item.id,
date: formattedDate,
rating,
title: itemCtx.item.title,
authors: itemCtx.item.authors,
image: itemCtx.item.image,
comment,
};
myBooksCtx.updateMyBooks(mybook);
navigate("/my-books", { replace: true });
};
activeClassName -> isActive
activeClassName が削除されたため、代わりに isActive を使用して、特定のナビゲーションがアクティブかどうかを認識する必要があります.
v5
const MainNavigation = () => {
return (
<header className={classes.header}>
<div className={classes.logo}>Your Library</div>
<nav className={classes.nav}>
<ul>
<li>
<NavLink to="/search-book" exact activeClassName={classes.active}>
Home
</NavLink>
</li>
<li>
<NavLink to="/my-books" activeClassName={classes.active}>
My Books
</NavLink>
</li>
<li>
<NavLink to="/" exact activeClassName={classes.active}>
Logout
</NavLink>
</li>
</ul>
</nav>
</header>
);
}
v6
const MainNavigation = () => {
return (
<header className={classes.header}>
<div className={classes.logo}>Your Library</div>
<nav className={classes.nav}>
<ul>
<li>
<NavLink
to="/search-book"
className={({ isActive }) => (isActive ? classes.active : null)}
>
Home
</NavLink>
</li>
<li>
<NavLink
to="/my-books"
className={({ isActive }) => (isActive ? classes.active : null)}
>
My Books
</NavLink>
</li>
<li>
<NavLink
to="/"
className={({ isActive }) => (isActive ? classes.active : null)}
>
Logout
</NavLink>
</li>
</ul>
</nav>
</header>
);
};
リダイレクト -> ナビゲート
Redirect は使っていませんが、Redirect の削除も v5 からの大きな変更点だと思います.代替コンポーネントはナビゲートですが、属性が少し変更されています. Redirect では、replace がデフォルトであり、必要に応じて push を使用しました.一方、Navigate では push がデフォルトであり、replace を使用する必要があります.
v5
<Redirect to="contactme" />
<Redirect to="home" push />
v6
<Navigate to="contactme" replace />
<Navigate to="home" />
the official document からより詳細な情報を見つけることができます.
このアップデートの私の印象は、v6 でネストされたパスを処理しやすくなったということです.また、要素を使用するため、ページ コンポーネントとその他のコンポーネントを分離することがより重要になります.これにより、コーディングがよりクリーンになると思います.ただし、activeClassName の削除は、私にとっては少し不便です.
読んでくれてありがとう :)
元の記事は here です
Reference
この問題について(React Router: v5 からの更新), 我々は、より多くの情報をここで見つけました https://dev.to/lada496/react-router-updating-from-v5-kjjテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol