I’m developing a Gutenberg Block for WordPress and I’m getting stuck with the logic.
I need to fetch some data to populate a ComboboxControl to allow the user to select one option.
So far I could make it work but when the post is saved and the page is reloaded, the saved value of the Combobox cannot match any item from the list because it is loaded afterwards and the selected value appears blank even if it’s there. If I click inside the combobox and then outside, the selected value finally shows up.
I had to put the apiFetch request outside of the Edit function to prevent endless calls to the API but I’m not sure this is good practice.
So from there I’m not sure how to improve my code or how to use hooks such as useEffect.
I need to have my data fetched and, only then, render my ComboboxControl with all the options ready.
Here is my code from the edit.js file:
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import apiFetch from '@wordpress/api-fetch';
import { ComboboxControl, SelectControl } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import './editor.scss';
var options = [];
apiFetch( { path: '/wp/v2/posts/?per_page=-1' } ).then( ( posts ) => {
console.log( posts );
if ( posts.length ) {
posts.forEach( ( post ) => {
options.push( { value: post.id, label: post.title.rendered } );
} );
}
}, options );
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const [filteredOptions, setFilteredOptions] = useState( options );
const updateGroupId = ( val ) => {
setAttributes( { GroupId: parseInt( val ) } );
}
return (
<div {...blockProps}>
<ComboboxControl
label="Group"
value={attributes.GroupId}
onChange={updateGroupId}
options={filteredOptions}
onFilterValueChange={( inputValue ) =>
setFilteredOptions(
options.filter( ( option ) =>
option.label
.toLowerCase()
.indexOf( inputValue.toLowerCase() ) >= 0
)
)
}
/>
</div>
);
}
2
Answers
I have the same problem…
adding my code here too as it is slightly different and might help finding the solution
I think you need some
useEffect
with your API results as a dependency, that did work for me, something likeLikely you would need a conditional around your Control, ie