get query object by Router.query empty in 9.2.1
when i use dynamic-routing, i come across that bug,
I would get query object by Router.query in componentDidMount func;
like this
public componentDidMount() {
console.log('Router.query', Router.query);
}
the query is empty
Go to example/dynamic-routing
modify the comment.js like as:
import Router from 'next/router';
class Comment extends React.Component<{}, {}> {
public componentDidMount() {
console.log('Router.query', Router.query);
}
public render() {
return (
<>
<h1>Post</h1>
</>
);
}
}
get query object by Router.query
I 'm also having this issue with 9.2.1
When I redirect from page A to page B by next/link, the router.query (from next/router) contains the data I want. However, when I refresh page B on browser, the router.query becomes empty.
@jamesmosier answer is only for logging the router.query
, but the point is router.query
is empty, so logging it doesn't fix the issue. I think it may be a bug.
Let me provide my code for reproduce:
import React, { Component } from 'react';
import { withRouter } from 'next/router';
import Link from 'next/link';
import { getBlogs } from '../../utils/blogs';
import './style.scss';
class Blogs extends Component {
render() {
const blogs = getBlogs();
return (
<main className="blogs-container">
{blogs.map(blog => (
<Link key={blog.id} href="/blog/[url]" as={`/blog/${blog.url}`}>
<a>{blog.title}</a>
</Link>
))}
</main>
)
}
}
export default withRouter(Blogs);
import React, { Component } from 'react';
import { withRouter } from 'next/router';
import './style.scss';
const countdownInterval = 1000;
class Game extends Component {
constructor(props) {
const { router } = props;
super(props);
console.log(router.query)
}
render() {
return (
<div>
some content here...
</div>
)
}
}
export default withRouter(Game);
Flow:
blogs
pagerouter.query
correctlyrouter.query
as emptyThis is correct behavior and documented here: https://nextjs.org/docs/routing/dynamic-routes#caveats
Pages that are statically optimized by Automatic Static Optimization will be hydrated without their route parameters provided, i.e query will be an empty object ({}).
After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.
This is correct behavior and documented here: https://nextjs.org/docs/routing/dynamic-routes#caveats
Pages that are statically optimized by Automatic Static Optimization will be hydrated without their route parameters provided, i.e query will be an empty object ({}).
After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.
thanks for helping. I just read the documentation again. It states that add getInitialProps
could disable Automatic Static Optimization and fix router.query
empty issue. I just tried to add it but still not working.
@ivanhoe-dev Please provide a reproduction so we can take a look and see what's wrong 馃檹
Closing as the OP issue was identified to be due to Automatic Static Optimization.
@ivanhoe-dev, per above by @lfades, provide a demo and we can take a look for you.
I just fixed the issue by changing my own code. I move the router.query
related code from constructor to render function. It seems because when refreshing page, the router.query
is empty initially. After I put it in the render function, it will re-render the page after router.query
is updated.
I still have this problem after running build (export) even though in console i see:
Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`.
go to: https://codesandbox.io/s/with-static-export-39rhb?fontsize=14&hidenavigation=1&theme=dark
, open console
and add some query param to url
@Timer @lfades
If you believe you've found a real bug with a full reproduction please open a new issue.
I used this method for class component:
import React, {Component} from 'react'
import {withRouter} from 'next/router';
export async function getServerSideProps(content) {
const {urlParam} = content.query;
return {props: {urlParam}}
}
...
render(){
return <h2>{this.props.urlParam}</h2>
}
...
export default withRouter(Comp);
Works after reload, hard reload too
This is an issue. In class components when we use withrouter along side static props, the query object is empty
I got the same problem..
I am sure this is the bugs
But for now I use something like this as workaround:
setTimeout(() => {
const { token, email } = this.props.router.query;
....
}, 0);
Same bug here. When console-logging router object, I can see the router.query
exists, but when I try to grab the parameters from the router.query
object, I get undefined. For now, I'm using window
object...
Same issue - router.query is empty on mount and an undetermined amount of time after. Option is to place it within a useEffect in which case it causes multiple re renders, or simply not use it.
Hi @joelwass
You can try my workaround above.. it works for me until this problem is solved
I got the same problem..
I am sure this is the bugsBut for now I use something like this as workaround:
setTimeout(() => { const { token, email } = this.props.router.query; .... }, 0);
This trick saddly doesn't work in my functional component ...
i used it in useEffect() but when i refresh the page, my query still turn to null
@concat1911 the workaround above is for class component..
I think this issue (null routing query) does not occur in functional component, as long as you use hooks.
Example:
const router = useRouter();
const { myRoutingParam, anotherParams } = router.query;
I believe you can always use window object and parse query params by yourself, e.g.
// URL: http://localhost:3000/sth?page=2
const SomeComponent = () => {
const router = useRouter();
useEffect(() => {
console.log(new URLSearchParams(window.location.search).get("page"));
}, []);
}
That seems to be a better solution than hacking with the event loop
For anyone still running into this issue, a full production build works for us meanwhile local dev gives a query
of {}
.
The following code cannot find input
when running next
, but works perfectly with next build && next start
componentDidMount() {
// does not work on dev, only when deployed
const input = this.props.router.query.input;
input && this.searchOnLoad(input);
}
We're on [email protected]
If like me, you are using getStaticProps
, the docs state:
Pages that are statically optimized by Automatic Static Optimization will be hydrated without their route parameters provided, i.e query will be an empty object ({}).
After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.
This means you can watch router.query
in useEffect
to check the params like so:
const router = useRouter();
useEffect(() => {
console.log(router.query);
}, [router.query]);
Or watch for a specific param:
const router = useRouter();
useEffect(() => {
console.log(router.query.myParam);
}, [router.query.myParam]);
Then How to render component depends on query params?
function SomeActiveLink() {
const router = useRouter()
const { view } = router.query
return (
<Link href="/some-href"}>
<a className={view==='active' ? 'active' : ''}>Active</a>
</Link>
)
}
I'm getting this warning because query is empty object on the server, any help is appreciated.
react_devtools_backend.js:2450 Warning: Prop className
did not match. Server: "active" Client: "";
Running into the same issue in development. I was trying to load a query parameter from the url when the component init, and use it as initial value for a hook:
const [searchFilter, setSearchFilter] = useState<string>(setSearchFilter(resolveInitialSearchFilter(router))');
console.log('router', router';
But this didn't work. The router
log shows 3 logs and the first one is systematically empty. (router.query
is an empty object, while router.path
contains the proper data).
Using @minlare trick with useEffect
worked around the problem.
const router: NextRouter = useRouter();
const [searchFilter, setSearchFilter] = useState<string>('');
useEffect(() => {
setSearchFilter(resolveInitialSearchFilter(router));
}, [router?.query?.[QUERY_SEARCH_FILTER_KEY]]);
Most helpful comment
If like me, you are using
getStaticProps
, the docs state:This means you can watch
router.query
inuseEffect
to check the params like so:Or watch for a specific param: