Using withRouter as a wrapper, shallow routing doesn't seem to be working.
I currently use this method to change the route:
this.props.router.push({
pathname: currentPath,
query: currentQuery,
});
And couldn't figure where to put the shallow flag. So I switched to the method mentioned in the docs:
this.props.router.push('/post/[pid]?hello=123', '/post/abc?hello=123', { shallow: true })
So I did that manually, but I started getting 404s.
http://localhost:3000/_next/static/development/pages/search/%5Btype%5D/%5Bcat%5D/%5Barea%5D.js net::ERR_ABORTED 404 (Not Found)
decoded:
"http://localhost:3000/_next/static/development/pages/search/[type]/[cat]/[area].js"
I tried using :type instead of [type] but it also didn't work.
This is how it's configured on the server:
if ('/search/:type/:cat/:area' === route.path) {
return app.render(req, res, route.page);
}
Folder Structure:
/pages/search/index.js
It should not reload the page while changing the route, that's the main thing I'm trying to accomplish.
I'm implementing SSR pagination, and I'm planning to use shallow routing to make page changes happen on the client instead of the server. Meaning achieve SSR of first load only, keep user in without refreshing.
This is might be related #4545
This works as follows:
server.js
server.get('/users/:username', (req, res) => {
return app.render(req, res, '/users/[username]', req.params)
})
usage on a page
props.router.push('/users/[username]?counter=10', '/users/foo?counter=10', { shallow: true });
Hello @jamesmosier
I tried what you mentioned above:
server.get('/search/:type/:cat/:area', (req, res) => {
console.log("reached here..."); // this gets logged
return app.render(
req,
res,
'/search/[type]/[cat]/[area]',
req.params
);
});
But I'm getting 404s, the page is not there now!
I managed to get those logs:
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?ts=1594623181340',
query: [Object: null prototype] { ts: '1594623181340' },
pathname: '/_next/static/development/pages/_app.js',
path: '/_next/static/development/pages/_app.js?ts=1594623181340',
href: '/_next/static/development/pages/_app.js?ts=1594623181340'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', 'pages', '_app.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?ts=1594623181340',
query: [Object: null prototype] { ts: '1594623181340' },
pathname: '/_next/static/runtime/webpack.js',
path: '/_next/static/runtime/webpack.js?ts=1594623181340',
href: '/_next/static/runtime/webpack.js?ts=1594623181340'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'runtime', 'webpack.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?ts=1594623181340',
query: [Object: null prototype] { ts: '1594623181340' },
pathname: '/_next/static/runtime/main.js',
path: '/_next/static/runtime/main.js?ts=1594623181340',
href: '/_next/static/runtime/main.js?ts=1594623181340'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'runtime', 'main.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?ts=1594623181340',
query: [Object: null prototype] { ts: '1594623181340' },
pathname: '/_next/static/development/dll/dll_d6a88dbe3071bd165157.js',
path: '/_next/static/development/dll/dll_d6a88dbe3071bd165157.js?ts=1594623181340',
href: '/_next/static/development/dll/dll_d6a88dbe3071bd165157.js?ts=1594623181340'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', 'dll', 'dll_d6a88dbe3071bd165157.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?ts=1594623181340',
query: [Object: null prototype] { ts: '1594623181340' },
pathname: '/_next/static/development/_buildManifest.js',
path: '/_next/static/development/_buildManifest.js?ts=1594623181340',
href: '/_next/static/development/_buildManifest.js?ts=1594623181340'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', '_buildManifest.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/development/dll/dll_d6a88dbe3071bd165157.js.map',
path: '/_next/static/development/dll/dll_d6a88dbe3071bd165157.js.map',
href: '/_next/static/development/dll/dll_d6a88dbe3071bd165157.js.map'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', 'dll', 'dll_d6a88dbe3071bd165157.js.map' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/runtime/webpack.js.map',
path: '/_next/static/runtime/webpack.js.map',
href: '/_next/static/runtime/webpack.js.map'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'runtime', 'webpack.js.map' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/chunks/0.js',
path: '/_next/static/chunks/0.js',
href: '/_next/static/chunks/0.js'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'chunks', '0.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/runtime/main.js.map',
path: '/_next/static/runtime/main.js.map',
href: '/_next/static/runtime/main.js.map'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'runtime', 'main.js.map' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/chunks/0.js.map',
path: '/_next/static/chunks/0.js.map',
href: '/_next/static/chunks/0.js.map'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'chunks', '0.js.map' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/development/pages/_app.js.map',
path: '/_next/static/development/pages/_app.js.map',
href: '/_next/static/development/pages/_app.js.map'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', 'pages', '_app.js.map' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/development/pages/_error.js',
path: '/_next/static/development/pages/_error.js',
href: '/_next/static/development/pages/_error.js'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', 'pages', '_error.js' ] }
_next/static catchall' -> generateRoutes -> parsedUrl Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/_next/static/development/pages/_error.js.map',
path: '/_next/static/development/pages/_error.js.map',
href: '/_next/static/development/pages/_error.js.map'
}
_next/static catchall' -> generateRoutes -> params { path: [ 'development', 'pages', '_error.js.map' ] }
Could you provide a full repository showing this issue?
I have the exact same file structure and am able to get this to work.
pages/search/[type]/[cat]/[area].js
<button
type="button"
onClick={() => {
props.router.push('/search/[type]/[cat]/[area]?counter=10', '/search/foo/bar/baz?counter=10', { shallow: true });
}}
>
go
</button>
server.js
server.get('/search/:type/:cat/:area', (req, res) => {
return app.render(req, res, '/search/[type]/[cat]/[area]', req.params)
})
url http://localhost:3000/search/foo/bar/baz and clicking button shallow routes and add a ?counter=10 query string suffix.
I'll try to prepare a separate repo tonight, hopefully.
But just to make sure that your repro is the same as mine, do you have a search folder in pages dir with index.js?
/pages/search/index.js
This means there are no [type].js nor [cat].js nor [area].js pages.
also the params aren't in english, they're in arabic, so decoding/encoding might has something to do with that.
Anyways. I'll try to prepare the repo ASAP.
Hello @jamesmosier
You can find the repo here https://github.com/omar-dulaimi/nextjs-shallow-routing-repro
currently the search page won't render, you can find a comment on the server how I currently get it to render.
Please let me know if there's anything I could change.
This should work:
server.get('/search/:type/:cat/:area', (req, res) => {
return app.render(req, res, '/search', {
...req.params,
...req.query,
});
});
props.router.push(
'/search?type=foo&cat=bar&area=baz&counter=10',
'/search/foo/bar/baz?counter=10',
{ shallow: true }
);
Hey @jamesmosier
This seems promising, like it rendered the page it actually added a query param without reloading the page.
But I noticed that it does nothing with consequent clicks, could you share your working repo please?
import React from "react";
import Router, { withRouter } from "next/router";
class SearchPage extends React.Component {
constructor(props) {
try {
super(props);
this.state = {
counter: 0,
};
} catch (e) {
console.log(
"pages => search => index.js => SearchPage -> constructor -> e",
e
);
}
}
componentDidMount() {
}
render() {
const { counter } = this.state;
return (
<button
type="button"
onClick={() => {
Router.push(
`/search?type=foo&cat=bar&area=baz&counter=${counter}`,
`/search/foo/bar/baz?counter=${counter + 1}`,
{ shallow: true }
);
}}
>
go
</button>
);
}
}
export default withRouter(SearchPage);
My working test case just displays what you mentioned originally in this issue that shallow rendering works with a custom server and dynamic routes. It:
added a query param without reloading the page
which should resolve this issue.
As for your other issue, I'm not sure what that tests case is supposes to do.
`/search?type=foo&cat=bar&area=baz&counter=${counter}`,
`/search/foo/bar/baz?counter=${counter + 1}`,
would be
`/search?type=foo&cat=bar&area=baz&counter=0`,
`/search/foo/bar/baz?counter=1`,
which would be different counter values
It works great now.
Thanks a lot for your time and effort.
@jamesmosier