How do i get all Custom Posts in the list.js to work?

Hi,
im having a Problem with modifying the list.js. First what i did: i created in WordPress an custom endpoint for the web-api where all posts and custom posts are “stored” at. Now im trying to modify the list.js so its gets all posts from the custom endpoint i created. How do i accomplish this ?
thanks for any help :slight_smile:

Hi! @nkuDev

You need to create a custom handler for that.

In my project I have a file called handlers.js:

const casesHandler = {
  pattern: "/cases/",
  func: async ({ route, params, state, libraries }) => {
    const response = await libraries.source.api.get({
      endpoint: "cases-api?_embed"
    });
    const cases = await libraries.source.populate({ response, state });

    Object.assign(state.source.data[route], {
      isCases: true,
      isPostType: false,
      items: cases.map(item => ({
        type: item.type,
        id: item.id,
        link: item.link
      }))
    });
  }
};
const caseHandler = {
  pattern: "/case/:slug/",
  func: async ({ route, params, state, libraries }) => {
    const response = await libraries.source.api.get({
      endpoint: "cases-api?_embed"
    });

    const [_case] = await libraries.source.populate({ response, state });

    Object.assign(state.source.data[route], {
      id: _case.id,
      type: _case.type,
      isCaseType: true,
      isCases: false,
      isFrontPage: false
    });
  }
};

export const CustomPageHandlers = [casesHandler, caseHandler]

In my index.js I have something like this:

/**
   * Actions are functions that modify the state or deal with other parts of
   * Frontity like libraries.
   */
  actions: {
    theme: {
      init: ({ libraries }) => {
        // Use html2react to process the <img> tags inside the content HTML.
        libraries.html2react.processors.push(image);

        // Add the handler to wp-source. Import CustomPageHandlers from './handlers.js'
        CustomPageHandlers.forEach(handlers => {
          libraries.source.handlers.push(handlers);
        });
      },
      toggleMobileMenu: ({ state }) => {
        state.theme.isMobileMenuOpen = !state.theme.isMobileMenuOpen;
      },
      closeMobileMenu: ({ state }) => {
        state.theme.isMobileMenuOpen = false;
      }
    }
  },

Then in your Cases component for example you can take the data something like this:

const Cases = ({ state, actions }) => {
  // Get the data of category cases.
  const data = state.source.get("/cases/");

  useEffect(() => {
    actions.source.fetch("/cases/");
    List.preload();
  }, []);

  if (!data.isReady) return <div>loading...</div>;

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

  return (
    <>
      {cases.map(item => (
        <div key={item.slug}>{item.title.rendered}</div>
      ))}
    </>
  );
};

I hope this will help! :wink:

4 Likes

Hi @christian.nascimento , this is quite helpfull but im realtive new to Frontity so could you please explain more about the isCases and isPostType ? Where are they coming from ? I can’t get it to work. Either im getting an Error like: Internal Server Error or something is not working like: Cannot read property of “rendered” || “source” and so on. Maybe you got any idear how to fix this.
Thanks for any reply :slight_smile:

Hi @nkuDev

The isCases and isPostType are properties that exist on the state provided by the @frontity/wp-source. Those properties are in turn based on the WP Template Hiererchy.

Have a look at https://docs.frontity.org/api-reference-1/wordpress-source#state and see if that helps.

The Internal Server Error would indicate that there is an issue on the server side in the endpoint that you have developed.

It’s hard to say what “rendered” || “source” without seeing the rest of the component that is fetching the data. Could you post it here?

1 Like

Yeah, we will be able to help you if you post the code of the handler here :slight_smile:

Hi @luisherranz & @mmczaplinski , sorry for the late reply. My handler is looking like this:

And my CustomPosts component is looking like this:
CustomPostsComponent

Hi @nkuDev!
The code looks correct at first sight. What is the error message that you receive?

@mmczaplinski This is what i get when im going to my site localhost:3000/posts/:

Is it possible that you have forgotten to wrap your CustomPosts component with connect()? :sweat_smile:

2 Likes

Indeed i did :smiley: But still it’s not showing any Posts… :confused:

Hi @nkuDev! :wink: How are your index.js file? You are importing your component into it?

Like:

import CustomPosts from '../components/CustomPosts';
...
const Theme = ({ state }) => {
  // Get information about the current URL.
  const data = state.source.get(state.router.link);
  const { isMobileMenuOpen } = state.theme;
  ...
  <Main id="main">
  ...
  (data.isPostType && <CustomPosts />) || 
  ...

You also need to change your handler Object.assign. Remove isCases and change isPostType to true

I hope this will help you. :wink:

Hi @christian.nascimento, i did change my handler and Yes im importing it right :slight_smile: Maybe you can see something that i might mabye miss in my index.js file.

My index.js file is looking like this:

Thanks for the help :smiley:

:smiley: Have you tried to remove your non custom post component from rendering? Try to remove (data.isPostType && <Post />)

1 Like

We are working on a Switch component to make routing more simple and easier to understand: Switch component

I hope it helps with this type of misunderstandings.

1 Like

I tried it but still doesn’t work :confused:

What type of content are you trying to cover with CustomPosts? Is it a custom post type? Is it a taxonomy?

Yes, it is a custom post type.

Which one?

It’s still a custom post type. The “post_type” is called “test_type” for eksample.

Not sure if it’s your problem, but I’ve seen that you didn’t define a priority on your handler, and the url /posts/ is matching the posts handler pattern too. If you add priority: 5 (for example), you make sure your custom handler runs instead of the default one. You have more info about this in our docs.

Apart from that, did you import connect from frontity at the beginning of the file? Your CustomPosts component should look something like this:

import React from "react";
import { connect } from "frontity";

const CustomPosts = ( { state, actions, libraries } ) => {
  ...
};

export default connect( CustomPosts );

Could you try that and tell us if it solves your problem?