【まるっと解決】React Router v4.0.0 で「Uncaught TypeError: Cannot read property 'location' of undefined」が起きた時の対処法
JavaScript、JSON、ReactJS における React Router v^4.0.0 で発生する "Uncaught TypeError: Cannot read property 'location' of undefined" エラーの詳細な解説と解決策
React Router v^4.0.0 で、以下のエラーが発生する場合があります。
Uncaught TypeError: Cannot read property 'location' of undefined
このエラーは、location
オブジェクトにアクセスしようとしたときに発生します。location
オブジェクトは、ブラウザの現在の URL 情報を含むオブジェクトです。
原因
このエラーが発生する主な原因は以下の 2 つです。
- コンポーネント内で useHistory フックを使用していない
useHistory
フックは、React Router v6 で導入された新しいフックです。このフックを使用すると、ブラウザの履歴情報を操作したり、現在の URL 情報を取得したりすることができます。
解決策
以下のいずれかの方法で、エラーを解決することができます。
useHistory フックを使用する
import React from 'react';
import { useHistory } from 'react-router-dom';
const MyComponent = () => {
const history = useHistory();
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
</div>
);
};
import React from 'react';
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
const location = useLocation();
return (
<div>
<p>現在の URL: {location.pathname}</p>
</div>
);
};
withRouter 高階コンポーネントを使用する
import React from 'react';
import { withRouter } from 'react-router-dom';
const MyComponent = ({ history, location }) => {
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
<p>現在の URL: {location.pathname}</p>
</div>
);
};
export default withRouter(MyComponent);
BrowserRouter コンポーネントをルートコンポーネントにラップする
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
補足
- React Router v6 以降では、
useHistory
フックとuseLocation
フックを使用するのが推奨されています。 withRouter
高階コンポーネントは、React Router v6 以降でも使用できますが、useHistory
フックとuseLocation
フックの方が簡潔で使いやすいです。BrowserRouter
コンポーネントは、React Router v6 以降でも必要です。
上記以外にも、エラーの原因となる可能性はあります。エラーメッセージの詳細を確認したり、デバッガーを使用して問題箇所を特定したりすることをお勧めします。
React Router v^4.0.0 で "Uncaught TypeError: Cannot read property 'location' of undefined" エラーが発生しないサンプルコード
import React from 'react';
import { useHistory } from 'react-router-dom';
const MyComponent = () => {
const history = useHistory();
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
</div>
);
};
import React from 'react';
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
const location = useLocation();
return (
<div>
<p>現在の URL: {location.pathname}</p>
</div>
);
};
import React from 'react';
import { withRouter } from 'react-router-dom';
const MyComponent = ({ history, location }) => {
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
<p>現在の URL: {location.pathname}</p>
</div>
);
};
export default withRouter(MyComponent);
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
React Router v^4.0.0 で "Uncaught TypeError: Cannot read property 'location' of undefined" エラーを解決するその他の方法
withRouter
高階コンポーネントを使用して、コンポーネントに history
と location
プロパティを注入することができます。
import React from 'react';
import { withRouter } from 'react-router-dom';
const MyComponent = ({ history, location }) => {
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
<p>現在の URL: {location.pathname}</p>
</div>
);
};
export default withRouter(MyComponent);
import React from 'react';
import { Router, BrowserRouter } from 'react-router-dom';
const MyContext = React.createContext({
history: null,
location: null,
});
const MyComponent = ({ children }) => {
const { history, location } = React.useContext(MyContext);
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
<p>現在の URL: {location.pathname}</p>
{children}
</div>
);
};
const App = () => {
const history = useHistory();
const location = useLocation();
return (
<MyContext.Provider value={{ history, location }}>
<BrowserRouter>
<MyComponent>
{/* 子コンポーネント */}
</MyComponent>
</BrowserRouter>
</MyContext.Provider>
);
};
カスタムフックを使用して、history
と location
オブジェクトをコンポーネントから取得することができます。
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
const useRoute = () => {
const history = useHistory();
const location = useLocation();
return { history, location };
};
const MyComponent = () => {
const { history, location } = useRoute();
return (
<div>
<button onClick={() => history.push('/new-page')}>新しいページへ</button>
<p>現在の URL: {location.pathname}</p>
</div>
);
};
react-router-dom バージョンを更新する
このエラーは、react-router-dom
の古いバージョンが原因で発生する可能性があります。react-router-dom
の最新バージョンに更新してみてください。
コードを確認する
上記のいずれの方法を試しても問題が解決しない場合は、コードを確認してエラーの原因となっている箇所がないかを確認してください。
javascript json reactjs