Hello @joppe could you provide a public repo or a codesandbox reproducing the error? This way it will be easier for the community to help you.
The code I got working doesnāt assign data
but rather pulls items.items
to an items
property and that works well.
Hello Pablo,
Sorry I cannot provide a public repo or sandbox.
Maybe I can rephrase my question a bit.
The method Object.assign
expects two properties. The first one is the target property where the key/values will be copied to. In the example state.source.data["primaryMenu"]
is provided. In my case this property is undefined, so the assign wonāt work. Should the property be created by the framework? Is there a setting I should add, so it will be generated?
This is the code I use
import * as React from 'react';
import Theme from './Theme';
const menuHandler = {
name: 'primaryMenu',
pattern: 'primaryMenu',
priority: 10,
func: async ({ libraries, state }): Promise<void> => {
const response = await libraries.source.api.get({
endpoint: 'menu/all',
});
const items = await response.json();
Object.assign(state.source.data['primaryMenu'], {
items,
isMenu: true,
});
},
};
export default {
name: 'zimpa',
roots: {
theme: Theme,
},
actions: {
theme: {
beforeSSR: async ({ actions }): Promise<void> => {
await actions.source.fetch('primaryMenu');
},
},
},
libraries: {
source: {
handlers: [menuHandler],
},
},
};
Hey @joppe,
I am going to try to answer this, but please someone correct me if I am wrong.
When you use actions.source.fetch('primaryMenu')
that will use the primaryMenu handler to fetch a certain endpoint. In your case I can see the endpoint is 'menu/all'
.
As far as I understand, when get request is performed, the response is placed in state.source.data[link]
. The idea is to then wait for the reposnse to resolve and get the items from it and add them to that object in state.source.data[link]
.
I believe in your case you need to look at state.source.data['menu/all']
. The easiest way to test this is just open the browser console, type frontity.state.source.data
and review what you have there. This will help you find the solution.
Good luck and hopefully this was helpful in 1 way or another.
I quick suggestion (not sure if it is the solution) in addition to what was explained by @ni.bonev
const menuHandler = {
name: 'primaryMenu',
pattern: 'primaryMenu',
priority: 10,
func: async ({ link, libraries, state }): Promise<void> => {
const response = await libraries.source.api.get({
endpoint: 'menu/all',
});
const items = await response.json();
Object.assign(state.source.data[link], {
items,
isMenu: true,
});
},
};
What Iām doing here is using the param link from the function, because if I remember correctly, the link will be primaryMenu/
. Thatās the reason you get undefined, because the link is being modified to always have a /
at the end.
Hi,
I followed your example and I can call the menus, but I have an issue; I canāt access the resources of these different menus;
Could you please help me?
Hi @eudeskouassi
In order to get help most efficiently itās essential that you provide a bit more details about your problem:
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.
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!
Well done on figuring that out - the clue is in the name: SSR!
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.