Using wp.data.subscribe properly

Viewed 4161

How to use wp.data.subscribe to Show/Hide a block for a certain Post Format (Audio, Video, and Gallery), I test this code and it's working good BUT it triggered while writing the post content and when select any other option so the target block flicker while writing.

wp.data.subscribe(() => {

    var postFormat = wp.data.select('core/editor').getEditedPostAttribute('format');


    $('#blockAudio, #blockVideo, #blockGallery').hide();


    if( postFormat == 'gallery' ) {

      $('#blockGallery').fadeIn();

    }

});
2 Answers

wp.data.subscribe is a wrapper around Redux's store.subscribe.

From the Redux docs:

subscribe(listener) adds a change listener. It will be called any time an action is dispatched, and some part of the state tree may potentially have changed. You may then call getState() to read the current state tree inside the callback.

My interpretation: wp.data.subscribe is, by design, called every single time a change occurs in the current state. While editing posts in the editor, the state is changed enumerable times, so it makes sense that the listener function is called every single time. My bet is that you should check yourself if a relevant part of the state has changed, and then do the thing you want.

So I think you could modify your code something like this:

const getPostFormat = () => wp.data.select('core/editor').getEditedPostAttribute('format');

// set the initial postFormat
let postFormat = getPostFormat();

wp.data.subscribe(() => {

    // get the current postFormat
    const newPostFormat = getPostFormat();    

    // only do something if postFormat has changed.
    if( postFormat !== newPostFormat ) {

      // Do whatever you want after postFormat has changed
      if (newPostFormat == 'gallery') {
        $('#blockAudio, #blockVideo, #blockGallery').hide();
        $('#blockGallery').fadeIn();
      }

    }
    
    // update the postFormat variable.
    postFormat = newPostFormat;

});

Sources:

I have faced this problem and solved it by another solution I have given display: none; to my all meta boxes within CSS file. like this:

#fw-options-box-link,
#fw-options-box-video,
#fw-options-box-gallery,
#fw-options-box-audio,
#fw-options-box-quote {
    display: none;
}

then in my javascript file, I wrote the following:

jQuery(document).ready(function ($) {
    /*''''''''''''''''''''''''''''''''''''' /   Standard Optns  */
    "use strict";
    var standerOptions = jQuery('#no_options'); //metabox ID
    var standerTrigger = jQuery('#post-format-0'); //post format ID
    /*''''''''''''''''''''''''''''''''''''' /   Quote Optns  */
    var quoteOptions = $('#fw-options-box-quote');
    var quoteTrigger = jQuery('#post-format-quote');
    /*''''''''''''''''''''''''''''''''''''' /   Video Optns  */
    var videoOptions = jQuery('#fw-options-box-video');
    var videoTrigger = jQuery('#post-format-video');
    /*''''''''''''''''''''''''''''''''''''' /   Gallery Optns  */
    var galleryOptions = jQuery('#fw-options-box-gallery');
    var galleryTrigger = jQuery('#post-format-gallery');
    /*''''''''''''''''''''''''''''''''''''' /   Link Optns  */
    var linkOptions = $('#fw-options-box-link');
    var linkTrigger = jQuery('#post-format-link');
    /*''''''''''''''''''''''''''''''''''''' /   Audio Optns  */
    var audioOptions = jQuery('#fw-options-box-audio');
    var audioTrigger = jQuery('#post-format-audio');
    /*''''''''''''''''''''''''''''''''''''' /   Image Optns  */
    var imageOptions = jQuery('#no_options');
    var imageTrigger = jQuery('#post-format-image');
    /*''''''''''''''''''''''''''''''''''''' /   Core  */
    $(document).on('change', 'select[id*="post-format"],#post-formats-select input', function () {
        // alert(this.value);
        linkOptions.show();
        if (this.value == 'video') {
            videoOptions.css('display', 'block');
            reyHideAll(videoOptions);
        } else if (this.value == '0') {
            standerOptions.css('display', 'block');
            reyHideAll(standerOptions);
        } else if (this.value == 'quote') {
            quoteOptions.css('display', 'block');
            reyHideAll(quoteOptions);
        } else if (this.value == 'gallery') {
            galleryOptions.css('display', 'block');
            reyHideAll(galleryOptions);
        } else if (this.value == 'link') {
            linkOptions.css('display', 'block');
            reyHideAll(linkOptions);
        } else if (this.value == 'image') {
            imageOptions.css('display', 'block');
            reyHideAll(imageOptions);
        } else if (this.value == 'audio') {
            audioOptions.css('display', 'block');
            reyHideAll(audioOptions);
        } else {
            standerOptions.css('display', 'none');
            quoteOptions.css('display', 'none');
            linkOptions.css('display', 'none');
            imageOptions.css('display', 'none');
            videoOptions.css('display', 'none');
            audioOptions.css('display', 'none');
            galleryOptions.css('display', 'none');
        }
    });

    if (standerTrigger.is(':checked'))
        standerOptions.css('display', 'block');

    if (quoteTrigger.is(':checked'))
        quoteOptions.css('display', 'block');

    if (videoTrigger.is(':checked'))
        videoOptions.css('display', 'block');

    if (galleryTrigger.is(':checked'))
        galleryOptions.css('display', 'block');

    if (imageTrigger.is(':checked'))
        imageOptions.css('display', 'block');

    if (linkTrigger.is(':checked'))
        linkOptions.css('display', 'block');

    if (audioTrigger.is(':checked'))
        audioOptions.css('display', 'block');

    function reyHideAll(notThisOne) {
        videoOptions.css('display', 'none');
        standerOptions.css('display', 'none');
        quoteOptions.css('display', 'none');
        galleryOptions.css('display', 'none');
        imageOptions.css('display', 'none');
        audioOptions.css('display', 'none');
        linkOptions.css('display', 'none');
        notThisOne.css('display', 'block');
    }
});

you can convert this code to be suitable for you
Related