I am having issues passing in query objects to useRouter()
hook. I am attempting to capture URL params and pass it into a page component pages/post.js
server-side using koa.
and koa-router
.
I am using Koa.js
as my middleware based on next.js example: custom-koa-server
and using Next's documentation: Custom routes (using props from URL)
// server.js
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
router.get("/post/:slug", async ctx => {
await app.render(ctx.req, ctx.res, "/post", { slug: ctx.params.slug });
ctx.respond = false;
});
router.get("*", async ctx => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
});
server.use(async (ctx, next) => {
ctx.res.statusCode = 200;
await next();
});
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
// pages/post.js
import { useRouter } from "next/router";
const Post = () => {
const router = useRouter();
console.log(useRouter());
const { slug } = router.query;
return <p>My Blog Post: {slug}</p>;
};
export default Post;
useRoute() console.log
// output: console.log(useRoute());
ServerRouter {
route: '/post',
pathname: '/post',
query: { amp: undefined },
asPath: '/post/testing' }
When attempting to access the query
object, no matter what, I get { amp: undefined }
Any help on this will be super helpful! Thank you in advance!
Hi! Questions belong on our Spectrum, please open a support request there with a reproduction repository.
Also, in your provided code I don't see the need for a custom server, dynamic routes would fulfill your needs:
https://nextjs.org/docs#dynamic-routes
@Timer Thanks! Apologies for the misplacement...issue posted here
oh and the reason why I am not using Dynamic Routes is that this will eventually be a server-side fetch to an API and passed rendered into a page component. Details in the General Channel of Next.js Spectrum.
Does getInitialProps
not support what you're trying to do?
i have the same problem锛孒ow did you solve it
@jingyuanhe
All you need to do to resolve this is useEffect to make sure it runs after router has initialized.
For example:
const [queryId, setQueryId] = useState(null)
useEffect(()=> {
if(router && router.query) {
setQueryId(router.query.id)
}
}, [router])
It seems a bit user-unfriendly that the router.query
is not properly initialized until first render. What's the technical reasoning behind this?
This is the workaround I used:
const queryString = require('query-string'); // https://www.npmjs.com/package/query-string
const { filters } = queryString.parse(router.asPath.substring(1));
I noticed that router.query
was missing the query params as my component was re-rendered, but they were correct on router.asPath
. I parse the params manually from that instead.
It seems a bit user-unfriendly that the
router.query
is not properly initialized until first render. What's the technical reasoning behind this?
There can't be a good reason, it's a bug. The returning of the router object SHOULD block by default, or we should be able to configure it to block until the query attribute has been set.
Most helpful comment
It seems a bit user-unfriendly that the
router.query
is not properly initialized until first render. What's the technical reasoning behind this?