…register it using libraries.source.handlers.push(homeHandler);
in actions.theme.init and implement the component.
This works fine. But now, I would like to show the newest articles in my home page component. Is there any shorter way to achieve that without implementing a separate fetching logic (calling libraries.source.api.get and populating)? Right now, the data in state.source.get("/") is missing of course and I need to do basically the same which the frontity archive handler does.
Any ideas, information and best practices are welcome
Thank you!
If I understood the case correctly you don’t need a handler for this. I think the best way would be to check if you are on the homepage (this info is already in Frontity state) and in that case, load a new component.
At the index.js file of your theme you should check if it’s the homepage, and if so load your <Home /> component:
Apart from that, you should create your <Home /> component where you can load whatever you want, including the latest posts. You could do something like this:
import React from "react";
import { connect, styled } from "frontity";
import Item from "./list-item";
const Home = ({ state }) => {
// Get the data of the latest posts.
const data = state.source.get(state.router.link);
return (
<Container>
<div>Some content before the posts</div>
<div>
<p>Load the posts here</p>
<div>
{data.items.map(({ type, id }) => {
const item = state.source[type][id];
// Render one Item component for each post.
return <Item key={item.id} item={item} />;
})}
</div>
</div>
<div>Some content after the posts</div>
</Container>
);
};
export default connect(Home);
This way, you’ll be importing the list-item that it’s already created (with its title, author, excerpt, etc), but you could also create a new one and import that instead.
That should be enough, let us know if it works in your case and if you have any other questions don’t hesitate to share them
Thank you really much, this solves my problem!
However, I’d like to do one additional thing: Right now, it’s possible to access URLs like /page/1 etc. Is it possible to (easily) prevent that with this solution? I know, it’s not the standard behaviour for a WP blog, but in my current state of the website I would like to restrict that. Thank you!
Not sure about this one, for sure @David can confirm if I am correct. What I thought was to use the parse method (explained here) to check if page is included and in that case return a 404. In your case it could be something like this:
import Page404 from "./page404";
const Home = ({ state, libraries }) => {
const currentLink = state.router.link;
// Get the data of the latest posts.
const data = state.source.get(currentLink);
// Get the page of the link.
let { page } = libraries.source.parse(currentLink);
if (page > 1) {
return <Page404 />;
} else {
return (
<div>
<div>Some content before the posts</div>
<div>
<p>Load the posts here</p>
<div>
{data.items.map(({ type, id }) => {
const item = state.source[type][id];
// Render one Item component for each post.
return <Item key={item.id} item={item} />;
})}
</div>
</div>
<div>Some content after the posts</div>
</div>
);
}
};
export default connect(Home);
Of course, you could change the page404 for other content if you want. I think this would solve your problem, but tell us if that’s not the case.
Thank you @SantosGuillamot! Sorry for answering that late. In my project, I wanted to completely avoid the possibility to access the main page by using URLs like /page/… - so I did some research how to check the initial page link and I found state.frontity.initialLink. So right now, I’ll check for state.frontity.initialLink != "/" and will return a 404 for the home page.
Ok, found out that this is stupid and initialLink is only the initial one when accessing the whole page.
My new solution:
I’ve extended frontity router state by router.activePageLink in router/index.ts: router: { link: string; activePageLink: string; };
Set “/” as initial active page link for state in tiny-router/index.ts: router: { link: "/", activePageLink: "/", autoFetch: true }
Set active page link for router actions init and set in tiny-router/actions.ts:
export const set: TinyRouter["actions"]["router"]["set"] = ({
state,
actions,
libraries
}) => (link): void => {
state.router.activePageLink = link;
// normalizes link
if (libraries.source && libraries.source.normalize)
link = libraries.source.normalize(link);
//...
export const init: TinyRouter["actions"]["router"]["init"] = ({
state,
actions,
libraries
}) => {
if (state.frontity.platform === "server") {
state.router.activePageLink = state.frontity.initialLink;
// Populate the router info with the initial path and page.
//...
I think it’s generally a good idea to save the actual page link in the state, since it seems that only the normalized version of the link is saved currently. What do you think?
Thanks, will have a look at your PR.
Sorry, the naming was confusing. What I meant with activePageLink was the full original path including parameters and pages, AFAIK this is only provided in a normalized form after calling libraries.source.normalize. I didn’t want any normalized link or page. My use case is that I want to restrict access to my home page only via using / and not via /page/..., so the only possibility I saw there was to check for the whole path.