如何从 Next.js 中的 URL 获取(查询字符串)参数?

How can I get (query string) parameters from the URL in Next.js?

当我点击 /index.js 中的 link 时,它会将我带到 /about.js 页面。

但是,当我通过 URL 传递参数名称时(如 /about?name=leangchhean)从 /index.js/about.js, 不知如何在/about.js页面获取

index.js

import Link from 'next/link';
export default () => (
  <div>
    Click{' '}
    <Link href={{ pathname: 'about', query: { name: 'leangchhean' } }}>
      <a>here</a>
    </Link>{' '}
    to read more
  </div>
);
  • about.js页面使用以下代码获取:

// pages/about.js
import Link from 'next/link'
export default ({ url: { query: { name } } }) => (
  <p>Welcome to About! { name }</p>
)

url 属性从 Next.js 版本 6 开始被弃用: https://github.com/zeit/next.js/blob/master/errors/url-deprecated.md

获取查询参数,使用getInitialProps:

对于无状态组件

import Link from 'next/link'
const About = ({query}) => (
  <div>Click <Link href={{ pathname: 'about', query: { name: 'leangchhean' }}}><a>here</a></Link> to read more</div>
)

About.getInitialProps = ({query}) => {
  return {query}
}

export default About;

对于常规组件

class About extends React.Component {

  static getInitialProps({query}) {
    return {query}
  }

  render() {
    console.log(this.props.query) // The query is available in the props object
    return <div>Click <Link href={{ pathname: 'about', query: { name: 'leangchhean' }}}><a>here</a></Link> to read more</div>

  }
}

查询对象会像:url.com?a=1&b=2&c=3变成:{a:1, b:2, c:3}

对于那些正在寻找适用于 static exports 的解决方案的人,请尝试此处列出的解决方案:https://github.com/zeit/next.js/issues/4804#issuecomment-460754433

简而言之,router.query 仅适用于 SSR 应用程序,但 router.asPath 仍然有效。

因此可以使用 exportPathMap(非动态)在 next.config.js 中配置查询 pre-export:

    return {
      '/': { page: '/' },
      '/about': { page: '/about', query: { title: 'about-us' } }
    }
  }

或者使用 router.asPath 并使用像 query-string:

这样的库自己解析查询
import { withRouter } from "next/router";
import queryString from "query-string";

export const withPageRouter = Component => {
  return withRouter(({ router, ...props }) => {
    router.query = queryString.parse(router.asPath.split(/\?/)[1]);

    return <Component {...props} router={router} />;
  });
};

使用路由器挂钩。

您可以在应用程序的任何组件中使用 useRouter hook

https://nextjs.org/docs/api-reference/next/router#userouter

传递参数

import Link from "next/link";

<Link href={{ pathname: '/search', query: { keyword: 'this way' } }}><a>path</a></Link>
要么
import Router from 'next/router'

Router.push({
    pathname: '/search',
    query: { keyword: 'this way' },
})

在组件中

import { useRouter } from 'next/router'

export default () => {
  const router = useRouter()
  console.log(router.query);

  ...
}

Post.getInitialProps = async function(context) {

  const data = {}
  try{
    data.queryParam = queryString.parse(context.req.url.split('?')[1]);
  }catch(err){
    data.queryParam = queryString.parse(window.location.search);
  }
  return { data };
};

import { useRouter } from 'next/router';

function componentName() {
    const router = useRouter();
    console.log('router obj', router);
}

我们可以在路由器中找到查询对象,使用它我们可以获得所有查询字符串参数。

如果您需要从组件外部检索 URL 查询:

import router from 'next/router'

console.log(router.query)

使用Next.js 9以上可以得到查询参数:

router:

import { useRouter } from 'next/router'

const Index = () => {
  const router = useRouter()
  const {id} = router.query

  return(<div>{id}</div>)
}

getInitialProps:

const Index = ({id}) => {
  return(<div>{id}</div>)
}

Index.getInitialProps = async ({ query }) => {
  const {id} = query

  return {id}
}

我知道两种方法:
Server-Side方式,Client-Side方式。

方法 #1:SSR(Server-Side 渲染):

您应该为该页面使用查询上下文
所以使用 getServerSideProps 而不是 getStaticProps

import React from "react";

export async function getServerSideProps(context) {
    const page = (parseInt(context.query.page) || 1).toString();
    // Here we got the "page" query parameter from Context
    // Default value is "1"
  
    const res = await fetch(`https://....com/api/products/?page=${page}`);
    const products = await res.json();
    return {props: {products: products.results}}
    // will be passed to the page component as props
  }

const Page = (props) =>{
    const products = props.products;
    return (
      <ul>
        {products.map((product) => (
            <li key={product.id}>{product.name}</li>
        ))}
      </ul>);
}

export default Page

原因是:这个数据不能pre-rendered在用户请求之前,所以它必须Server-Side在每次请求时呈现(SSR) .

  • 静态页面:使用getStaticProps
  • 更改内容:使用getServerSideProps
    这里的内容是根据查询参数
  • 改变的

参考:https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props

方法#2:下一个路由器(客户端):

import {useState, useEffect} from "react";
import { useRouter } from 'next/router'

const Page = () =>{
    const [products, setProducts] = useState([]);
    const [page, setPage] =useState((useRouter().query.page || 1).toString());
    // getting the page query parameter
    // Default value is equal to "1"

    useEffect(()=>{
      (async()=>{
        const res = await fetch(`https://....com/api/products/?page=${page}`);
        const products = await res.json();
        setProducts(products.results);
        // This code will be executed only once at begining of the loading of the page
        // It will not be executed again unless you cahnge the page
      })()
    },[page]);

    return (
      <ul>
        {products.map((product) => (
            <li key={product.id}>{product.name}</li>
        ))}
      </ul>
      );
}

export default Page

参考:https://nextjs.org/docs/api-reference/next/router

使用 {useRouter} from "next/router"; 有帮助,但有时您不会获得值,而是将参数名称本身作为值。 当您尝试通过 de-structuring 访问查询参数时会发生此问题,例如:

let { categoryId = "", sellerId = "" } = router.query;

对我有用的解决方案是尝试直接从查询对象访问值:

let categoryId  = router.query['categoryId'] || '';
let sellerId  = router.query['sellerId'] || '';