I have a block that references a custom post type named faq that has a taxonomy named faq_group. This block has one attribute and makes multiple getEntityRecords calls. One of the calls has an argument that depends on the previous one:
The attribute:
// the group attribute stores the slug of the selected faq_group slug from a SelectControl component
attributes: {
group: {
type: 'string',
default: '',
},
}
The calls:
// Get all terms from the faq_group taxonomy to fill a SelectControl component (name and slug)
const groups = useSelect( ( select ) =>
select( 'core' ).getEntityRecords( 'taxonomy', 'faq_group', { per_page: -1, orderby: 'name', order: 'asc', _fields: 'id,name,slug' } ),
[]
);
// Get the term object with the same slug as the group attribute
const selectedGroup = useSelect( ( select ) =>
select( 'core' ).getEntityRecords( 'taxonomy', 'faq_group', { per_page: -1, orderby: 'name', order: 'asc', _fields: 'id,name,slug' } )?.find( ( term ) => term.slug === attributes.group ),
[ attributes.group ]
);
// Get posts from the faq custom post type with a faq_group term with id = selectedGroup.id
const faqs = useSelect( ( select ) =>
select( 'core' ).getEntityRecords( 'postType', 'faq', { faq_group: [ selectedGroup?.id ] } ),
[ selectedGroup?.id ]
);
My question is, can this be simplified somehow? Can the multiple calls be combined inside just one useSelect selector?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Can the multiple calls be combined inside just one
useSelect
selector?
Yes, and here’s an example where my useSelect() returns an object that I unpack using the destructuring assignment (e.g. const { a, b } = myFunc() where myFunc() returns { a: 'foo', b: 123 }):
const { groups, selectedGroup, faqs } = useSelect( ( select ) => {
const { getEntityRecords } = select( 'core' );
// The args are identical for both "groups" and selectedGroup, so I put them in a constant.
const groupsArgs = { per_page: -1, orderby: 'name', order: 'asc', _fields: 'id,name,slug' };
const selectedGroup = getEntityRecords( 'taxonomy', 'faq_group', groupsArgs )?.find(
( term ) => term.slug === attributes.group
);
return {
groups: getEntityRecords( 'taxonomy', 'faq_group', groupsArgs ),
faqs: getEntityRecords( 'postType', 'faq', { faq_group: [ selectedGroup?.id ] } ),
selectedGroup,
};
}, [ attributes.group ] );
If you do not actually need to access the selectedGroup from outside the useSelect() callback, then you can omit selectedGroup from the list, i.e. use just const { groups, faqs } = useSelect( ... ), and then remove the selectedGroup, (the third line) from the return value.
And actually, instead of calling getEntityRecords() twice with the same args, you could call it just once:
const { groups, selectedGroup, faqs } = useSelect( ( select ) => {
const { getEntityRecords } = select( 'core' );
const groupsArgs = { per_page: -1, orderby: 'name', order: 'asc', _fields: 'id,name,slug' };
const groups = getEntityRecords( 'taxonomy', 'faq_group', groupsArgs );
const selectedGroup = groups?.find( ( term ) => term.slug === attributes.group );
return {
groups,
selectedGroup,
faqs: getEntityRecords( 'postType', 'faq', { faq_group: [ selectedGroup?.id ] } ),
};
}, [ attributes.group ] );
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0