如何在 class 组件中使用 next.js 中的 "useRouter()"?
How to use "useRouter()" from next.js in a class component?
我试图通过使用 "next/router" 中的 useRouter()
从我的 url 模式(如 localhost:3000/post?loc=100
中获取查询,并使用该 ID 从我的服务器获取一些数据。当我在无状态功能组件中使用它时它起作用了。
但是页面显示 "Invalid hook call" 然后。我尝试调用无状态功能组件的 getInitalProps()
,但它在那里也不起作用并显示相同的错误。
使用这种方法有什么规定吗?
我正在使用 React 库和 Next.js 框架开发前端。
constructor(props) {
this.state = {
loc: useRouter().query.loc,
loaded: false
};
}
Hooks 只能在功能组件内部使用,不能在 classes 内部使用。我建议根据 next.js 文档使用 withRouter HOC:
use the useRouter
hook, or withRouter
for class components.
如果您想切换到 hooks,请参阅 From Classes to Hooks。
通常,可以创建一个包装器功能组件以通过 props 将自定义挂钩传递到 class 组件(但在这种情况下没有用):
const MyClassWithRouter = (props) => {
const router = useRouter()
return <MyClass {...props} router={router} />
}
class MyClass...
constructor(props) {
this.state = {
loc: props.router.query.loc,
loaded: false
};
}
withRouter
例子
提到了它,但像我这样的新手需要更多细节。更 detailed/direct 的描述是:
函数组件:
import { useRouter } from "next/router";
export default function Post() {
const router = useRouter();
return (
<div>{ router.query.id }</div>
)
}
Class 等效分量:
import { withRouter } from 'next/router'
import React from "react";
export default withRouter(class extends React.Component {
render() {
return (
<div>{ this.props.router.query.id }</div>
)
}
})
我更具体地测试了这个,如下所示。首先,我拿了 vercel/next-learn-starter/basics-final/pages/posts/[id].js
并破解它以使用路由器:
diff --git a/basics-final/pages/posts/[id].js b/basics-final/pages/posts/[id].js
index 28faaad..52954d3 100644
--- a/basics-final/pages/posts/[id].js
+++ b/basics-final/pages/posts/[id].js
@@ -4,13 +4,17 @@ import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
+import { useRouter } from "next/router"
+
export default function Post({ postData }) {
+ const router = useRouter();
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
+ <div>router.query.id = {router.query.id}</div>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
然后,我运行它是:
git clone https://github.com/vercel/next-learn-starter
cd next-learn-starter
git checkout 5c2f8513a3dac5ba5b6c7621d8ea0dda881235ea
cd next-learn-starter
npm install
npm run dev
现在当我访问:http://localhost:3000/posts/ssg-ssr 我看到:
router.query.id = ssg-ssr
然后我将其转换为 class 等价物:
import Layout from '../../components/layout'
import { getAllPostIds, getPostData } from '../../lib/posts'
import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
import { withRouter } from 'next/router'
import React from "react"
export default withRouter(class extends React.Component {
render() {
return (
<Layout>
<Head>
<title>{this.props.postData.title}</title>
</Head>
<article>
<div>router.query.id = {this.props.router.query.id}</div>
<h1 className={utilStyles.headingXl}>{this.props.postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={this.props.postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: this.props.postData.contentHtml }} />
</article>
</Layout>
)
}
})
export async function getStaticPaths() {
const paths = getAllPostIds()
return {
paths,
fallback: false
}
}
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id)
return {
props: {
postData
}
}
}
一切似乎都没有改变。
在 Next.js 10.2.2.
上测试
我试图通过使用 "next/router" 中的 useRouter()
从我的 url 模式(如 localhost:3000/post?loc=100
中获取查询,并使用该 ID 从我的服务器获取一些数据。当我在无状态功能组件中使用它时它起作用了。
但是页面显示 "Invalid hook call" 然后。我尝试调用无状态功能组件的 getInitalProps()
,但它在那里也不起作用并显示相同的错误。
使用这种方法有什么规定吗?
我正在使用 React 库和 Next.js 框架开发前端。
constructor(props) {
this.state = {
loc: useRouter().query.loc,
loaded: false
};
}
Hooks 只能在功能组件内部使用,不能在 classes 内部使用。我建议根据 next.js 文档使用 withRouter HOC:
use the
useRouter
hook, orwithRouter
for class components.
如果您想切换到 hooks,请参阅 From Classes to Hooks。
通常,可以创建一个包装器功能组件以通过 props 将自定义挂钩传递到 class 组件(但在这种情况下没有用):
const MyClassWithRouter = (props) => {
const router = useRouter()
return <MyClass {...props} router={router} />
}
class MyClass...
constructor(props) {
this.state = {
loc: props.router.query.loc,
loaded: false
};
}
withRouter
例子
函数组件:
import { useRouter } from "next/router";
export default function Post() {
const router = useRouter();
return (
<div>{ router.query.id }</div>
)
}
Class 等效分量:
import { withRouter } from 'next/router'
import React from "react";
export default withRouter(class extends React.Component {
render() {
return (
<div>{ this.props.router.query.id }</div>
)
}
})
我更具体地测试了这个,如下所示。首先,我拿了 vercel/next-learn-starter/basics-final/pages/posts/[id].js
并破解它以使用路由器:
diff --git a/basics-final/pages/posts/[id].js b/basics-final/pages/posts/[id].js
index 28faaad..52954d3 100644
--- a/basics-final/pages/posts/[id].js
+++ b/basics-final/pages/posts/[id].js
@@ -4,13 +4,17 @@ import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
+import { useRouter } from "next/router"
+
export default function Post({ postData }) {
+ const router = useRouter();
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
+ <div>router.query.id = {router.query.id}</div>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
然后,我运行它是:
git clone https://github.com/vercel/next-learn-starter
cd next-learn-starter
git checkout 5c2f8513a3dac5ba5b6c7621d8ea0dda881235ea
cd next-learn-starter
npm install
npm run dev
现在当我访问:http://localhost:3000/posts/ssg-ssr 我看到:
router.query.id = ssg-ssr
然后我将其转换为 class 等价物:
import Layout from '../../components/layout'
import { getAllPostIds, getPostData } from '../../lib/posts'
import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
import { withRouter } from 'next/router'
import React from "react"
export default withRouter(class extends React.Component {
render() {
return (
<Layout>
<Head>
<title>{this.props.postData.title}</title>
</Head>
<article>
<div>router.query.id = {this.props.router.query.id}</div>
<h1 className={utilStyles.headingXl}>{this.props.postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={this.props.postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: this.props.postData.contentHtml }} />
</article>
</Layout>
)
}
})
export async function getStaticPaths() {
const paths = getAllPostIds()
return {
paths,
fallback: false
}
}
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id)
return {
props: {
postData
}
}
}
一切似乎都没有改变。
在 Next.js 10.2.2.
上测试