I have the following property with social icons:
items: {
type: 'array',
default: [
{ icon: 'twitter', url: '#' },
{ icon: 'facebook-square', url: '#' },
{ icon: 'youtube', url: '#' },
],
},
I have some controls:
<InspectorControls>
<PanelBody title={ __( 'Social Network Settings' ) } initialOpen={ true }>
{items.map( ( item, index ) => (
<Fragment>
<SelectControl
label="Social Network"
value={ item.icon }
options={ [
{ label: __( 'Twitter' ), value: 'twitter' },
{ label: __( 'Facebook' ), value: 'facebook-square' },
{ label: __( 'Instagram' ), value: 'instagram' },
{ label: __( 'YouTube' ), value: 'youtube' },
] }
onChange={ ( value ) => setAttributes( { items: [ ...items, { icon: value } ] } ) }
/>
<TextControl
label={ __( 'Social Link' ) }
value={ item.url }
onChange={ ( value ) => setAttributes( { items: [ ...items, { url: value } ] } ) }
/>
</Fragment>
) ) }
</PanelBody>
</InspectorControls>
And I'm rendering social icons:
{items.map( ( item, index ) => (
<a key={ index }
href={ item.url || '#' }
target="_blank"
>
<FontAwesomeIcon icon={['fab', item.icon]} />
</a>
) ) }
3 icons are showing. The correct icon name is showing in each select control. However when I change the icon in the select control, a new icon is added, instead of updating. The same goes when adding URLs, blank tags are being added.
How can I update the array when changing the select and text input?
The onChange
logic above implies that a new item will be added on each update.
Your onChange
should find the correct element and update it accordingly.
As example the onChange
forSocial Network
would look something similar to below. You should implement similar logic for the other onChange too.
onChange={( value ) => {
const newItem = {...item, icon: value };
const newItems = [...items];
newItems[index] = newItem;
setAttributes({ items: newItems });
}}