简体   繁体   English

如何在类组件中使用 next.js 中的“useRouter()”?

[英]How to use "useRouter()" from next.js in a class component?

I was trying to get the queries from my url pattern like localhost:3000/post?loc=100 by using useRouter() from "next/router" and fetching some data using that id from my server.我试图通过使用来自“next/router”的useRouter()并使用该 id 从我的服务器获取一些数据,从我的 url 模式中获取查询,例如localhost:3000/post?loc=100 It worked when I used it in a Stateless Functional Component.当我在无状态功能组件中使用它时,它起作用了。

But the page showing "Invalid hook call" then.但是页面显示“无效的钩子调用”。 I tried calling getInitalProps() of a Stateless Functional Component, but it didn't work there either and showed the same error.我尝试调用无状态功能组件的getInitalProps() ,但它也没有在那里工作并显示相同的错误。 Is there any rule to use this method?使用这种方法有什么规则吗?

I was developing a front-end using React Library and Next.js Framework.我正在使用 React 库和 Next.js 框架开发前端。

constructor(props) {
  this.state = {
    loc: useRouter().query.loc,
    loaded: false
  };
}

Hooks can be used only inside functional components, not inside classes.钩子只能在功能组件内部使用,不能在类内部使用。 I would recommend to use withRouter HOC as per next.js documentation:我建议按照 next.js 文档使用withRouter HOC:

use the useRouter hook, or withRouter for class components.对类组件使用useRouter钩子或withRouter

Or see From Classes to Hooks if you want to switch to hooks.或者 如果您想切换到钩子,请参阅 从类到钩子。


In general, it's possible to create a wrapper functional component to pass custom hooks into class components via props (but not useful in this case): 通常,可以创建一个包装器功能组件来通过 props 将自定义钩子传递到类组件中(但在这种情况下没有用):
 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 example withRouter示例

https://stackoverflow.com/a/57029032/895245 mentioned it, but a newbie like me needed a bit more details. https://stackoverflow.com/a/57029032/895245提到了它,但像我这样的新手需要更多细节。 A more detailed/direct description would be:更详细/直接的描述是:

Function component:功能组件:

import { useRouter } from "next/router";

export default function Post() {
  const router = useRouter();
  return (
    <div>{ router.query.id }</div>
  )
}

Class component equivalent:类组件等效:

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>
    )
  }
})

I tested this out more concretely as follows.我如下更具体地测试了这一点。 First I took vercel/next-learn-starter/basics-final/pages/posts/[id].js and I hacked it to use the router:首先,我使用了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} />

Then, I ran it as:然后,我运行它:

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

Now when I visit: http://localhost:3000/posts/ssg-ssr I see:现在当我访问:http://localhost:3000/posts/ssg-ssr 我看到:

router.query.id = ssg-ssr

Then I converted it to the class equivalent:然后我将其转换为等效的类:

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
    }
  }
}

and everything seemed to be unchanged.而一切似乎都没有改变。

Tested on Next.js 10.2.2.在 Next.js 10.2.2 上测试。

write your component and then، export it with withRouter(YourClassName) like :编写您的组件,然后使用withRouter(YourClassName)导出它,例如:

class App extends React.Component{
   render(){
        <h2> this is an example router query params : {this.props.router.query.id} <h2/>
     }
}
export default withRouter(Page)

so you can access router from component's prop like above example :)所以你可以像上面的例子一样从组件的 prop 访问路由器:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM