Hi,
I have a strange issue
I have created a small repo to reproduce it : https://github.com/mlecoq/nextjs-initialprops-issue
After static export :
There is two pages : index & details
In details I want to display query param
````
import React from 'react';
import Link from 'next/link';
const Details = ({ name }) =>
Details.getInitialProps = async ({ query: { name } }) => {
return { name };
};
export default Details;
````
When I click on a link from index (http://localhost) page to details (http://localhost/details/?name=testname), initial props is fired
but when I reload the page, my query param is not displayed in the page, initial props is not called
You ca reproduce the issue here:
https://out-fpdblcijhc.now.sh
| Tech | Version |
|---------|---------|
| next | 4.1.4 |
| node | 8.9.1 |
| OS | MacOs High Sierra |
| browser | Chrome |
I beat you to posting this by 7 hours :) #3313
You may have seen that I first commented your issue. After posting my comment I had a doubt, so I create a new one:
My expectation is that no API calls would be fired when loading subsequent routes accessed via
My use case is more low level and I have no consideration about api calls (with ou without Apollo)
Moreover, when I use Link without prefetch, I have a similar behavior but less predictable (mostly initialprops is fired but sometimes not)
You're right, it's the same topic (I am too doubtful 馃榿)
if I remove the _ async_ keyword (which is useless in my example) on InitialProps method, it works fine.
I have added in the example with 2 parameters, same issue without async
you can test it here:
https://out-sfintquivo.now.sh/
@timneutkens @arunoda, sorry to bother you, is there any workaround ?
Maybe this workaround is enough? https://github.com/zeit/next.js/issues/3313#issuecomment-361383026
I have made a small method
export const getParams = query => {
if (!query) {
return {};
}
return (/^[?#]/.test(query) ? query.slice(1) : query)
.split('&')
.reduce((params, param) => {
let [key, value] = param.split('=');
params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
return params;
}, {});
};
and then I use it in initialProps
Index.getInitialProps = ({ query: { name } }) => {
return { name : name ? name: getParams(window.location.search).name};
};
I also got bitten by this, another vote to try fixing this...
Sources + demo: https://github.com/tomimick/tm-nextjs-starter
My workaround:
componentDidMount() {
// get movie id (getInitialProps is not always called, Nextjs bug?)
let movie_id = this.props.id ? this.props.id : (new URLSearchParams(window.location.search)).get("id");
...
}
Digging into the source code for server/render and the export functionality.
getInitialProps is for server side only, if you run it once for an export and then write the output it is never going to make its way to the client.
I believe you just want your Details Page (top level) to look like this
const Details = ({ router }) => <div>Here is my .... name ! {router.query.name}div>;
I would vote to close this out ~ :+1:
Yes you're right, getting router query params is sufficient. Thanks !
Unfortunately it does not work with static export :(
My website is deployed on amazon so my url are ended with trailing slash.
When a trailing slash is present, router.query does not contain my param (whereas window.location.search do) when I reload the page
Hmm, it seems getInitialProps does get called in a static export if one enters the page with link, but is NOT called when doing a page refresh.
I also tried this approach:
componentDidMount() {
let movie_id = Router.query.id;
console.info("MovieDetailView did mount" + movie_id);
}
But also this fails in the same way: works when using a link, but fails when doing a page refresh.
Would be awesome if this could be fixed.
As my URIs don't have query strings, i found an (for now) acceptable workaround.
I use docuri, a helper that converts URIs to objects and vice versa.
Doing
const parseRoute = docuri.route('/:lang/:section/:slug');
const routeFragments = parseRoute(props.router.asPath);
parses a URI like /en/categories/my-category to
{
lang: "en",
section: "categories"
slug: "my-category"
}
@mlecoq: you could combine this with a check to see if there is a trailing slash and if necessary add or remove it before converting.
Maybe this helps.
Hey thinking about submitting a PR for this where the query is hydrated from window.location on createRouter https://github.com/drKnoxy/next.js/blob/canary/client/index.js#L96 if nextExport == true.
Is there anybody on core team who could offer some guidance before I blindly try to help out?
Probably addresses these
Holy Moley, the canary branch is pretty different from master. The fix is pretty much the same so I might submit a PR, but trying to run tests crashed my macbook pro and trying to npm link and test it crashed my app... So the canary flag is about right imo ;)
If anyone in the thread cares to patch this for their install....
Basically the router for export isn't getting the query parameter from the client (window.location), and needs to be.
// /node_modules/next/dist/client/index.js:24
var _querystring = require("querystring");
// /node_modules/next/dist/client/index.js:64
nextExport = _window$__NEXT_DATA__.nextExport,
dynamicIds = _window$__NEXT_DATA__.dynamicIds;
// /node_modules/next/dist/client/index.js:164
case 22:
exports.router = router = (0, _router2.createRouter)(
page,
// this line
nextExport ? (0, _querystring.parse)(location.search.replace(/^\?/, '')) : query,
asPath, {
initialProps: props,
pageLoader: pageLoader,
App: App,
Component: Component,
ErrorComponent: ErrorComponent,
err: initialErr
}
);
In the latest version of Next.js the querystring will be parsed even if a page did export statically.
Most helpful comment
Holy Moley, the canary branch is pretty different from master. The fix is pretty much the same so I might submit a PR, but trying to run tests crashed my macbook pro and trying to
npm linkand test it crashed my app... So the canary flag is about right imo ;)If anyone in the thread cares to patch this for their install....
Basically the router for export isn't getting the query parameter from the client (window.location), and needs to be.