i'm trying to implement my block element for wordpress with jsx, everything looks fine except this loop that didn't work. I try to update my attributes menuElem (an array with default: []) with a list coming from my fetch. But i keep having, outside the useEffect only one element stored in my attribute. Here's the code, i miss something but i'm lost right now :(
useEffect(
function () {
apiFetch({ path: "/wp/v2/menu-items/" }).then((items) => {
items.map((item, index) => {
if (item.menus === props.attributes.menuID) {
props.setAttributes({
menuElem: [
{
id: index,
url: item.url,
title: item.title.rendered,
},
],
});
}
});
});
},
[props.attributes.menuID]
);
And i want to loop in my jsx right after
return (
<div {...blockProps}>
<nav className="menu menu__main">
<ul>
{props.attributes.menuElem.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</nav>
</div>
);
I tried with something else, like working with an array where i push the results of my fetch, but the same problem keeps happening, the loop in useEffect is doing its job, but once i'm out of it, i keep having only one item instead of the whole result
The issue here is how you're using the map
function. map
returns an array after looping through all the items which I suspect is what you need menuElem
to be.
The current code would set the menuElem
repeatedly based on the condition, therefore overwriting the initial. At the end of the iteration, menuElem
is left with the last item that meets the condition.
Here is a revised version of the code using forEach
method instead
useEffect(() => {
apiFetch({ path: "/wp/v2/menu-items/" }).then((items) => {
const updatedMenuElem = [];
items.forEach((item, index) => {
if (item.menus === props.attributes.menuID) {
updatedMenuElem.push({
id: index,
url: item.url,
title: item.title.rendered,
});
}
});
// Update the attribute with the updatedMenuElem array
props.setAttributes({ menuElem: updatedMenuElem });
});
}, [props.attributes.menuID]);