How to fetch Menu from wordpress?

Hi @eudeskouassi :wave:
In order to get help most efficiently itā€™s essential that you provide a bit more details about your problem: :slight_smile:

What specific errors are you getting in the terminal?
What specific errors are you getting in the browserā€™s console?
If you could provide a repository with the code of your project, the community (or any member of the Frontity team) would be able to clone your project and try to reproduce the issue youā€™re having
With this info, itā€™ll be much easier to help you with your issue

If you canā€™t share your whole project, please create a CodeSandbox (you can start with this template) or a GitHub repository with the minimal amount of code to reproduce the issue.

Hi @SantosGuillamot
Pleqse, how to install this plugin https://github.com/WP-API/menus-endpoints ?

You can download the zip from the GitHub repo and upload it to your WordPress as any other plugin -> https://www.wonderplugin.com/wordpress-tutorials/how-to-manually-install-a-wordpress-plugin-zip-file/#:~:text=This%20tutorial%20will%20guide%20you,click%20the%20button%20Install%20Now.

Thank you !
Itā€™s okay

Is it possible to use Console.logs in the index.js files? I followed the instructions here and I have written the code correctly to get the menus using the WP-REST-v2 Menus plugin but I am getting items undefined in the Nav.js component.

The code in my index.js file.


const menuHandler = {

  name: 'menus',

  priority: 10,

  pattern: '/menus/:slug', // You can use something shorter here, you don't need to use the endpoint

  func: async ({ route, params, state, libraries }) => {

    const { api } = libraries.source

    const { slug } = params

    // 1. fetch the data you want from the endpoint page

    const response = await api.get({

      endpoint: `/menus/v1/locations/${slug}` 

    });

    // 2. get an array with each item in json format

    const items = await response.json();

   

    // 3. add data to source

    const currentPageData = state.source.data[route];

    Object.assign(currentPageData, {

      slug,

      items: items.items, // @ni.bonev figured this one out because the "items" property contains "items" that are the menu items we are after

      isMenu: true

    })

  }

}
beforeSSR: async ({ actions }) => {

      // Adding both menu location menus to beforeSSR

      await actions.source.fetch('/menus/primary')

      await actions.source.fetch('/menus/footer-menu')

  }
source: {

      handlers: [menuHandler]

    }

Hi @chinomsojohnson,

Welcome to the Community!

Can you please provide a repo or code-sandbox with your code? This is especially helpful to find solutions of technical issues with specific code

Regarding the use console.log in your code maybe this Frontity Talk we recently published about debugging may help you

Hi @mmczaplinski,
I was looking over these 3 options to create a menu myself. I initially went with option 3 using the plugin and custom handler. Subsequently I watched this talk from @SantosGuillamot - Connecting Gutenberg and Frontity ā€¦
It seems to me that creating the menu from a CPT or template part and using Gutenberg blocks and a processor is an easier way to go. Am I missing something? Iā€™m looking to use Frontity on a project at work and am wondering if there is a sort of list of best practices as it pertains to these common dev tasks.

Hi @sattley

Welcome to the Frontity community. Great to hear that youā€™re thinking of using Frontity for your work project.

Any of the 3 solutions proposed by @mmczaplinski will work fine and could be considered good practice. However, as with many technical decisions human considerations need to be factored in.

So, for example, if the people doing the content are already familiar with the WordPress admin pages and with working with WordPressā€™ menus then the plugin and custom handler would be the best option as the content creators/editors wonā€™t need to be taught a different way to do things.

On the other hand, if the content people are not already familiar with the WordPress admin then you could create the menu as a CPT and tell the content people that that is how it works for this site.

And then, as @mmczaplinski says, if the menu is unlikely to ever change or will change infrequently you could hard code it into frontity.settings.js and the developers can change it as and when it needs to be changed.

As I said earlier, itā€™s not always simply a technical decision. Take into account the users, and how theyā€™re going to work with and interact with the final technical solution.

Hi @mburridge,
Thanks for the quick response. Iā€™m going to use the solution that others have used since Iā€™d like to have the menus in WordPress still configurable by some non technical folks.

A few other questions if you donā€™t mind. Iā€™m learning Frontity and have been reading all of the docs first.
Right now Iā€™m just trying to console.log from the beforeSSR action, but it doesnā€™t seem to work. As I type this I just realized my error -> it logs to the terminal if I do npx frontity dev since thatā€™s the server, doh!

More questions to come Iā€™m sure, thanks!

Hi @david1,
Thanks for this solution. Rookie question for you but I noticed that your beforeSSR property it is not the same syntax as the Frontity documentation of:

{
beforeSSR: ({ state, libraries }) => {
console.log(ā€˜Gonna SSR this pageā€™);
}
}

but rather you have:

beforeSSR: async ({ actions }) => {}

How did you know to do this, ie the async and different parameter?
Thanks in advance!

Hi @sattley

Good approach! :ok_hand:

Well done on figuring that out - the clue is in the name: SSR! :grinning:

Feel free to ask. I look forward to helping wherever I can. Good luck with your project.

Hey @sattley,

So basically, the beforeSSR: ({actions}) is destructuring the object passed to it. The different parameter is what I need from the whole object, so I use the destructuring syntax {actions} to access it, instead of (object) and then later object.actions. Itā€™s just a shorthand of sorts in the new ECMAscript spec. In your case, you donā€™t need anything in your beforeSSR: () because you arenā€™t using anything. However, if you needed state or libraries, you would write what you did. Javascript functions donā€™t require a parameter be sent through if the function is provided one, you just want to pass the parameter if youā€™ll be using it.

As far as the async, I need it because Iā€™m using await in the function for await actions.source.fetch('/menus/primary-menu') and await actions.source.fetch('/menus/footer-menu'). Thatā€™s because the actions.source.fetch needs to wait for a response from the WordPress API before. If I donā€™t use await, the actions.source.fetch() calls will result in undefined data. Without async, await will through a Javascript error and the code will break.

1 Like

Just to add to what @david1 has said above, the frontity object has four properties, each of which is itself an object. The four properties are:

You can examine the object by entering frontity in the browser console, as you can see in this screenshot:

Hey @david1,

Appreciate the thorough response! I see - I was confused in looking at the docs and didnā€™t read closely enough that beforeSSR is just a function triggered at a certain time by Frontity that you can tap into. I read the examples as method signatures, my fault. Again greatly appreciate the help!

1 Like

Hi @mburridge,
Thank you for the quick feedback. I was actually watching a video with you in it last night where you were delving into what Frontity objects you can inspect in the console, very helpful! Thank you!

2 Likes

Hi Michael @mburridge,
Ok more questions :grinning:
Also please let me know if I should be creating new posts for these or if there is a specific protocol. My next questions are related to my WP data source. Iā€™m using a locally run version of WordPress. Here is the code from my frontity.settings.js

{
ā€œnameā€: ā€œ@frontity/wp-sourceā€,
ā€œstateā€: {
ā€œsourceā€: {
ā€œurlā€: ā€œhttps://ripple-web.lndo.site/ā€,
}
}
},

With this setup I get an error on the server console like this:

`FetchError: request to https://ripple-web.lndo.site/wp-json/wp/v2/posts?_embed=true&slug=footer-about-us failed, reason: unable to verify the first certificate`

I can use a locally run version of the site with a non https url:

`http://ripple-web.lndo.site/`

When I do this my frontity site loads the header and footer but in the middle of the page I get the ā€™ Oops! Something went wrong message. The error in the browser console is:

GET http://ripple-web.lndo.site/wp-json/wp/v2/posts?_embed=true&page=1 401 (Unauthorized)

Obviously these are 2 separate issues but either way Iā€™m not able to connect to my data source. Any help or direction greatly appreciated! Thanks!

Hi @sattley

Iā€™m not an expert on web security, but I found this answer about adding the root certificate to your application.

This may guide you in the right direction, or alternatively turn off https for that site on your local host. As itā€™s just local on your dev machine you donā€™t necessarily need https/ssl unless youā€™re specifically developing something that depends on it.

Hi @mburridge,
Thanks for the quick response. I fear Iā€™m getting pretty despondent with development so far, seem to be so many errors, though I feel like the majority of it is because its WordPress :slight_smile:

Iā€™d love any help, so here is where Iā€™m at currently. Iā€™m trying to output some menu content like other people in this thread.

  • Iā€™ve set my state.source.url to my locally running wordpress site which uses http. So Iā€™m no longer getting that error about the certificate.

  • In the beforeSSR action I have this code:

    beforeSSR: async ({actions}) => {
    await actions.source.fetch('http://ripple-web.lndo.site/wp-json/menus/v1/menus/footer-about-us') // this invokes our footerMenuHandler
  }
  • The resource at this address:
    ā€¦/wp-json/menus/v1/menus/footer-about-us returns the correct JSON I need.

  • I get this error:

ServerError: post type from endpoints ā€œposts,pages,mediaā€ with slug ā€œfooter-about-usā€ not found
at Object.eval (webpack-internal:///./node_modules/@frontity/wp-source/src/libraries/handlers/postType.ts:37:21)
at runMicrotasks ()
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at eval (webpack-internal:///./node_modules/@frontity/wp-source/src/actions.ts:24:1) {
status: 404,
statusText: ā€˜post type from endpoints ā€œposts,pages,mediaā€ with slug ā€œfooter-about-usā€ not foundā€™
}

Iā€™d love any help on this, thanks!

Hi @sattley

Enter the URL http://ripple-web.lndo.site/wp-json/menus/v1/menus/footer-about-us into a browser address bar. Do you get anything? i.e. do you know thatā€™s the correct endpoint?

Hi @mburridge,
Yep, itā€™s the correct endpoint - it returns me the JSON I need for my menu. Here is a partial screen grab of whatā€™s returned in the browser. I cropped it since Iā€™m guessing itā€™s enough to show itā€™s working.