Search code examples
wordpresswordpress-gutenberg

WordPress/Gutenberg : An error occurred while running 'mapSelect': Cannot read property


I created 4 custom post types : 'dissertation', 'subject-free', 'subject-imposed', 'curriculum-vitae'

I have created a metabox that I want to display on 3 custom post types : 'dissertation', 'subject-free', 'subject-imposed'.

When I want to create a post on 'curriculum-vitae'. I got an error : Error: An error occurred while running 'mapSelect': Cannot read property '_metafield_presentation' of undefined

import { __ } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { TextareaControl, Toolbar, ToolbarButton } from '@wordpress/components';
import { formatBold, formatItalic, link } from '@wordpress/icons';

const TextController = (props) => {
    const meta = useSelect(
        (select) => select('core/editor').getEditedPostAttribute('meta')['_metafield_presentation']
    );
    const { editPost } = useDispatch('core/editor');
    return (
        <TextareaControl
        label={__("Ajoutez ici votre texte de présentation permettant de décrire votre sujet libre. Vous pouvez vous inspirer de votre note d'intention en faisant un copier-coller. La limite est de 800 caractères maximum.", "textdomain")}
        value={meta}
        onChange={(value) => editPost({ meta: { _metafield_presentation: value } })}
        />
    );
};

const PluginDocumentSettingPanelDemo = () => (
    <PluginDocumentSettingPanel name="text-presentation" title="Texte de présentation" className="custom-panel-presentation">
    <TextController />
    </PluginDocumentSettingPanel>
);

registerPlugin('plugin-document-setting-panel-presentation', {
    render: PluginDocumentSettingPanelDemo,
    icon: null
});

And in functions.php :

function ccn_register_metas() {
    $post_types = [
        'dissertation',
        'subject-free',
        'subject-imposed'
    ];

    foreach ( $post_types as $post_type ) {

        register_post_meta(
            $post_type,
            '_metafield_presentation',
            array(
                'show_in_rest' => true,
                'type' => 'string',
                'single' => true,
                'sanitize_callback' => 'sanitize_text_field',
                'auth_callback' => function() {
                    return current_user_can( 'edit_posts' );
                },
            )
        );

    }

}

add_action('init', 'ccn_register_metas');

What's wrong please ?


Solution

  • The post meta hasn't been registered on the curriculum-vitae post type, so WordPress isn't able to update it. WordPress is trying to update it because the PluginDocumentSettingPanel is still being rendered on the curriculum-vitae post type.

    I usually do a check of the post type before working with any custom post meta or adding any PluginDocumentSettingPanels for that post type:

    const postType = useSelect( ( select ) => {
        return select( 'core/editor' ).getCurrentPostType();
    } );
    
    if ( postType === 'your-post-type' ) {
        // Do something with the post meta here
    }
    

    A more complete example:

    import { __ } from '@wordpress/i18n';
    import { registerPlugin } from '@wordpress/plugins';
    import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
    import { useSelect } from '@wordpress/data';
    import { TextControl } from '@wordpress/components';
    import { useEntityProp } from '@wordpress/core-data';
    
    const MyPlugin = () => {
        const postType = useSelect( ( select ) => {
            return select( 'core/editor' ).getCurrentPostType();
        } );
    
        const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
    
        if ( postType !== 'my-post-type' ) {
            // Not the correct post type, so we don't need to render this document setting panel
            return null;
        }
    
        return (
            <PluginDocumentSettingPanel
                name="my-plugin"
                title={ __( 'Plugin Title', 'text-domain' ) }
            >
                <TextControl
                    label={ __( 'Text Field', 'text-domain' ) }
                    value={ meta._meta_name ? meta._meta_name : '' }
                    onChange={ ( value ) => setMeta( { _meta_name: value } ) }
                />
            </PluginDocumentSettingPanel>
        );
    };
    
    registerPlugin( 'my-plugin', {
        render: MyPlugin,
        icon: '',
    } );