Closed tymoxx closed 2 years ago
@gopolar I think you cant, because the server wont know what is a page or post, cause they have same structure on root
You can try this on server.js , but i dont know if it will work
server.get("/:post", (req, res) => {
const actualPage = "/post";
const queryParams = { post: req.params.post};
app.render(req, res, actualPage, queryParams);
});
server.get("/:page", (req, res) => {
const actualPage = "/page";
const queryParams = { post: req.params.page};
app.render(req, res, actualPage, queryParams);
});
Maybe someone can help to achieve it by adding (or modifying) the API on the Wordpress side?
@gopolar It should work without modifications on the WP side but could be an issue only if a page and a post have the same slug. Wordpress can't distinguish one from another and will choose the higher hierarchy, which is page!
What @rubenmarcus said works. Check the server.js,post.js and page.js in this example. As you have page and post routes, such as /wp-json/wp/v2/pages/?slug=your-page-name-her and /wp-json/wp/v2/posts/?slug=your-page-name-her you should get correct data.
Hi @goranefbl, are you sure it works when you go to the page/post through the browsers URL (not by clicking the links)?
Actually, you are right...no idea why it worked for me on ssr which was during the refresh, probably forgot about caching....:/
Oh well, the only solution I see here is to create a custom route or use a plugin like this https://github.com/elevati/wp-api-multiple-posttype to enable query on both page and post via single route. Then route can give you both content and what post type it is (page or post), then use that type to load the template for a page or for a post.
I finally made a solution.
In api-routes.php I modified the function rest_get_post
:
function rest_get_post( WP_REST_Request $request ) {
if ( get_page_by_path($request->get_param( 'slug' ))){
$type = 'page';
} else {
$type = 'post';
}
return rest_get_content( $request, $type, __FUNCTION__ );
}
server.js:
server.get("/:slug", (req, res) => {
const actualPage = "/post";
const queryParams = { slug: req.params.slug, apiRoute: "post" };
app.render(req, res, actualPage, queryParams);
});
menu.js, inside the <Link>
tag:
as={item.object === 'post' || item.object === 'page' ? `/${slug}` : `/${item.object}/${slug}`}
And remember to remove 'post/' and 'page/' in other pages (like index.js and category.js) in the as
attributes for <Link>
.
Amazing solution @gopolar! Thanks a lot, helped me :) One question though, I have a page that needs a special template that cannot be page.js and so far I solved that using this:
server.js
server.get("/tjanster", (req, res) => {
const actualPage = "/tjanster";
const queryParams = { slug: req.params.slug, apiRoute: "tjanster" };
app.render(req, res, actualPage, queryParams);
});
api-routes
function rest_get_tjanster( WP_REST_Request $request ) {
return rest_get_content( $request, 'tjanster', __FUNCTION__ );
}
But now when I try to access /tjanster it only gives me a 404, is there anything I could do to work around that?
@gopolar The solution worked in the previous version. However, the new update got rid of the api-routes.php file and this seems to still be unsolved.
Would an endpoint like https://github.com/jackreichert/a-wp-react-redux-theme/blob/master/lib/endpoints/pretty-permalinks.php solve this problem?
This is what I'm using with Next
// server.js
// Will match anything like: https://domain/whatever
server.get('/:slug', (req, res) => {
const actualPage = '/page';
const queryParams = { slug: req.params.slug };
app.render(req, res, actualPage, queryParams);
})
// page.js
import React, { Component } from 'react';
import Query from '../lib/Query';
import App from '../components/App';
import withError from '../hoc/withError';
class Page extends Component {
static async getInitialProps({
query, req, res,
}) {
if (!query.slug && !req) {
return false;
}
const slug = query.slug ? query.slug : req.params.slug;
// Query is just an abstraction of Fetch. It does some error handling and normalizes response.
const data = await Query(
`/wp-json/littlebot/v1/page?slug=${slug}`,
res,
);
return data;
}
render() {
const { data } = this.props;
return (
<App>
<div className="site__content">
<article className="article">
<h1>{data.title.rendered}</h1>
<div dangerouslySetInnerHTML={{ __html: data.content.rendered }} />
</article>
</div>
</App>
);
}
}
// withError is a HOC to check if there is an actual page.
export default withError(Page);
// withError.js
import React from 'react';
import ErrorPage from 'next/error';
export default Component => class WithError extends React.Component {
static async getInitialProps(ctx) {
let props = Component.getInitialProps ? await Component.getInitialProps(ctx) : false;
if (!props) {
props = {};
props.statusCode = 404;
}
return props;
}
render() {
if (this.props.statusCode !== 200) {
return <ErrorPage statusCode={404} />;
}
return <Component {...this.props} />;
}
};
I am migrating my Wordpress website to Next.js with the following URL structure: "example.com/awesome-post" "example.com/awesome-page"
How I can keep the URLs without "/post/" or "/page/", but load the correct post and page, respectively.
"example.com/awesome-post" instead of "example.com/post/awesome-post" "example.com/awesome-page" instead of "example.com/page/awesome-page"