Retrieve all posts of CPT without knowing slugs

OK, I thought this was simple, but apparently I can’t manage it myself and after looking in the documentation and forums for a while I still can’t figure it out, so I’m asking for help. I’m probably totally missing one step in the process.

What I want is to create a Team component that loops through all posts of the custom post type called ‘team’, but currently I can’t manage to populate Frontity with the posts of that CPT.

The enpoint for the CPT is:
https://frontity.noesteprojecten.nl/wp-json/wp/v2/team

So far I’ve added the CPT to frontity.settings.js:

...
postTypes: [
  ...
  {
    type: "team",
    endpoint: "team",
    archive: "/team-archive",
  },
]
...

Added the CPT to my beforeSSR (is this even right for this purpose?):

beforeSSR: async ({ state, actions }) => {
  await Promise.all(
    [
      actions.source.fetch("/team"),
    ]
  );
},

And then started working on a component Team:

import React, {useEffect} from "react";
import { connect, styled } from "frontity";

const Team = ({ state, actions, libraries }) => {

   useEffect(() => {
      // No need to use `async/await` here
      actions.source.fetch('/team')
   }, []);

   // The data will not exist at first, `dataPost.isReady` will be false.
   // But then, it will rerender when `actions.source.fetch` is finished.
   const dataPost = state.source.get("/team");

   // This will work just fine.
   dataPost.isReady ? console.log(dataPost, state.source.team) : console.log('nope...');

   return null;
}

export default connect(Team);

However, dataPost returns an error: post type from endpoints \"posts,pages,media\" with slug \"team\" not found. But when I visit the archive page for team, the post type does exists: https://frontity-test-ten.now.sh/team-archive

After visiting the CPT archive page, the posts are available for the Team component. But of course I need to have them available on the front page already. So I think I will still need to populate Frontity with the posts from the CPT, but what is the correct procedure for this?

This is a link to my repo:
https://bitbucket.org/noesteijver/frontity/src/master/

I think I solved part of the problem by writing a handler, adding it to the handlers and using it in the beforeSSR. Is this really needed when you want to use posts outside of the archive loop and single page?

const teamHandler = {
  name: 'team',
  priority: 20,
  pattern: 'team',

  func: async ({ route, params, state, libraries }) => {
    // 1. get products data
    const response = await libraries.source.api.get({
      endpoint: 'team',
      params: {per_page: 100},
    });

    const entitiesAdded = await libraries.source.populate({ response, state });

    Object.assign(state.source.data[route], {
      isTeam: true,
      isPostType: true,
      items: entitiesAdded.map(item => ({
        type: item.type,
        id: item.id,
        link: item.link
      }))
    });
  }
}

...

beforeSSR: async ({ state, actions }) => {
  // getNameAndDescription,
  await Promise.all(
    [
...
      Object.values(teamHandler).map(() =>
        actions.source.fetch("team"),
      ),
...
    ]
  );
},
...
source: {
  handlers: [teamHandler],
}

Now I could see that state.source.team was populated, but odd enough I still had lots of trouble to use the data, but after loads of trial & error I managed to, but I’m unsure if this is the proper way of doing it. My team.js looks like this now.

import React, {useEffect} from "react";
import { connect, styled } from "frontity";
import Member from "./member";
import Item from "./list/list-item";

const Team = ({ state, actions, libraries }) => {
   useEffect(() => {
      actions.source.fetch("team");
    }, []);

    const data = state.source.get("team");

   if (data.isReady) {
      const members = data.items.map(({ type, id }) => state.source[type][id]);

      return (
         <>
            <h1>Team</h1>
            <MemberContainer>
               {data.items.map(({ type, id }, index) => {
               const item = state.source[type][id];
                  return <Member item={item} />;
               })}
            </MemberContainer>
         </>
      );
   }

   return null;
}

export default connect(Team);

const MemberContainer = styled.div`
...
`;

And finally, the member component looks like this:

import React, {useEffect} from "react";
import { connect, styled } from "frontity";
import FeaturedMedia from "./featured-media";
import Title from "./title"

const Member = ({ state, item, count }) => {
   return (
      <MemberItem href={item.link}>
         <FeaturedMedia id={item.featured_media} />
         <h2 dangerouslySetInnerHTML={{ __html: item.title.rendered }} />
         <div dangerouslySetInnerHTML={{ __html: item.excerpt.rendered }} />
      </MemberItem>
   );

   return null;
}

export default connect(Member);

const MemberItem = styled.a`
...
`;

My biggest problem at the moment is that the FeaturedMedia component won’t work. If I visit the specific page of a member and return to the front-page, the image is there. If I visit the page of another member and return to the front-page, the image is there, but the other image is gone. I looked how the component is used in list-item.js of the Mars theme, but I’m not seeing any specifics that I’m missing. So I’m unsure why the image is gone.

I’m really at a loss. If I’ve got the id of the featured-image in item.featured_media, this should just be working, am I right?

<FeaturedMedia id={item.featured_media} />

Or am I missing a crucial step in the process of fetching the attachment? I was under the impression that the FeaturedMedia component was always working when feeded an id, but maybe I’m wrong.

I cracked it, I guess.

I had to use the location of the archive in the fetch function. I configured the post-type to have team-archive as archive location, but when I changed this to team, things started to work…

   useEffect(() => {
      actions.source.fetch("/team/");
   });

   const data = state.source.get("/team/");

Is this assumption correct?