如何从 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
使用 {useRouter} from "next/router";
有帮助,但有时您不会获得值,而是将参数名称本身作为值。
当您尝试通过 de-structuring 访问查询参数时会发生此问题,例如:
let { categoryId = "", sellerId = "" } = router.query;
对我有用的解决方案是尝试直接从查询对象访问值:
let categoryId = router.query['categoryId'] || '';
let sellerId = router.query['sellerId'] || '';
当我点击 /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
使用 {useRouter} from "next/router";
有帮助,但有时您不会获得值,而是将参数名称本身作为值。
当您尝试通过 de-structuring 访问查询参数时会发生此问题,例如:
let { categoryId = "", sellerId = "" } = router.query;
对我有用的解决方案是尝试直接从查询对象访问值:
let categoryId = router.query['categoryId'] || '';
let sellerId = router.query['sellerId'] || '';