When using useRouter()聽in a class that extends React.Component the following error is thrown:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
import React from 'react';
import { useRouter } from 'next/router'
import Link from 'next/link'
import Header from '../../../components/header'
class Post extends React.Component {
render() {
const router = useRouter()
const { id } = router.query
return (
<>
<Header />
<h1>Post: {id}</h1>
<ul>
<li>
<Link href='/post/[id]/[comment]' as={`/post/${id}/first-comment`}>
<a>First comment</a>
</Link>
</li>
<li>
<Link href='/post/[id]/[comment]' as={`/post/${id}/second-comment`}>
<a>Second comment</a>
</Link>
</li>
</ul>
</>
)
}
}
export default Post;
useRouter() to work as expected.
Could possibly be related to #7626
withRouter() HOC can be used as workaround.
The error message delivered by React strictly states that Hooks work within "the body of a function component".
You must use withRouter if using a class component, or wrap the class with a functional component that passes along the router.
@Timer my bad, misinterpreted the error message. 馃槄
Thank you for the quick reply!
Hey, guys. Could you give an example of how to use withRouter in this case?
To access the router inside getInitialProps, just have getInitialProps take in router as a parameter. To access it anywhere else, use this.props.router. And don't forget to wrap the exported component with withRouter() :smiley:
```import React, { Component } from 'react';
import { withRouter } from 'next/router';
class SomePage extends Component {
constructor(props) {
super(props);
this.state = { something: 0 };
}
static async getInitialProps(router) {
const res = await fetch(http://localhost:3000/some-api/${router.query.id}/);
const data = await res.json();
console.log(Data is: ${data});
return {
data: data,
};
}
render() {
return (
Here is the id that was passed: {this.props.router.query.id}
);export default withRouter(SomePage);
```
The first parameter of getInitialProps is not router, it's a context object with many values.
You can find an example of how to use useRouter here: https://github.com/zeit/next.js#userouter
For whom who are searching for an example with class component:
import React, { Component } from "react";
import { withRouter } from 'next/router'
class Login extends Component {
constructor(props) {
super(props);
}
onClickHandler = (event) => {
this.props.router.push('/newPage')
}
render() {
return (
<div>
<p>Hello, {this.props.router.pathname}</p>
<button onClick={this.onClickHandler}>Click me!</button>
</div>
);
}
}
export default withRouter(Login);
Most helpful comment
Hey, guys. Could you give an example of how to use
withRouterin this case?