React Router v6 で withRouter を使うべき理由と使い方
React Router v6 で withRouter を使うべき理由と使い方
withRouter
は、React Router v5 以前でコンポーネントに history
や location
などのルーター情報を渡すために使用されていた高階コンポーネントです。
v6 で withRouter は必要?
v6 では、useLocation
や useNavigate
などのフックを使って、コンポーネント内で直接ルーター情報にアクセスできます。
なぜ withRouter を使うべき?
以下の状況では、withRouter
を使う方が便利で効率的です。
-
複数のコンポーネントで同じルーター情報を共有する場合:
-
コンポーネントが別のコンポーネントにラップされている場合:
withRouter の使い方
import { withRouter } from "react-router-dom";
const MyComponent = ({ location, history }) => {
// ...
};
const WrappedComponent = withRouter(MyComponent);
まとめ
v6 では withRouter
は必須ではありませんが、特定の状況では依然として役立ちます。
import React, { useState } from "react";
import { withRouter } from "react-router-dom";
const MyComponent = ({ location, history }) => {
const [count, setCount] = useState(0);
const handleClick = () => {
// `history` を使って別のページに移動
history.push("/about");
};
return (
<div>
<h1>カウント: {count}</h1>
<button onClick={handleClick}>別のページへ移動</button>
<p>現在のパス: {location.pathname}</p>
</div>
);
};
const WrappedComponent = withRouter(MyComponent);
export default WrappedComponent;
このコードでは、MyComponent
は withRouter
を使って高階コンポーネントに変換されています。
このコードを実行すると、以下のようになります:
- ユーザーがボタンをクリックすると、
history.push
を使って/about
ページに移動します。 location.pathname
は、現在のページのパスを表示します。
この例では、withRouter を使って以下のことを実現しています:
MyComponent
にlocation
とhistory
を渡すhistory
を使って別のページに移動
withRouter 以外の方法
useLocation と useNavigate フック
import { useLocation, useNavigate } from "react-router-dom";
const MyComponent = () => {
const { pathname } = useLocation();
const navigate = useNavigate();
const handleClick = () => {
navigate("/about");
};
return (
<div>
<h1>現在のパス: {pathname}</h1>
<button onClick={handleClick}>別のページへ移動</button>
</div>
);
};
カスタムフック
複数のコンポーネントで同じルーター情報を共有したい場合は、カスタムフックを作成できます。
import { useLocation, useNavigate } from "react-router-dom";
const useMyRouter = () => {
const { pathname } = useLocation();
const navigate = useNavigate();
return { pathname, navigate };
};
const MyComponent = () => {
const { pathname, navigate } = useMyRouter();
const handleClick = () => {
navigate("/about");
};
return (
<div>
<h1>現在のパス: {pathname}</h1>
<button onClick={handleClick}>別のページへ移動</button>
</div>
);
};
レンダープロパティパターン
コンポーネントにルーター情報を渡すための別の方法は、レンダープロパティパターンを使用することです。
import { useLocation, useNavigate } from "react-router-dom";
const MyComponent = ({ render }) => {
const { pathname } = useLocation();
const navigate = useNavigate();
return render({ pathname, navigate });
};
const App = () => {
return (
<MyComponent
render={({ pathname, navigate }) => (
<div>
<h1>現在のパス: {pathname}</h1>
<button onClick={() => navigate("/about")}>別のページへ移動</button>
</div>
)}
/>
);
};
コンポーネントツリーのコンテキスト
コンポーネントツリー全体でルーター情報を共有したい場合は、コンテキストを使用できます。
import React, { createContext } from "react";
import { useLocation, useNavigate } from "react-router-dom";
const RouterContext = createContext();
const MyComponent = () => {
const { pathname } = useLocation();
const navigate = useNavigate();
return (
<RouterContext.Provider value={{ pathname, navigate }}>
<MyChildComponent />
</RouterContext.Provider>
);
};
const MyChildComponent = () => {
const { pathname } = useContext(RouterContext);
return (
<div>
<h1>現在のパス: {pathname}</h1>
</div>
);
};
const App = () => {
return (
<RouterContext.Provider value={{ pathname: "/", navigate: () => {} }}>
<MyComponent />
</RouterContext.Provider>
);
};
withRouter
は、コンポーネントにルーター情報を渡すための便利な方法ですが、v6 では必須ではありません。
状況に応じて、useLocation
と useNavigate
などのフック、カスタムフック、レンダープロパティパターン、コンポーネントツリーのコンテキストなどの他の方法を使用することもできます。
reactjs react-router