WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.52k stars 4.21k forks source link

How to wait for Select onchange async fetch event to complete so results render in inspectorcontrols #27357

Closed mikebhart closed 2 years ago

mikebhart commented 3 years ago

Hello, Hope you can help.

Im fairly new to gutenberg so please bear with me.

I have the the following code, On my select onchange event I want the results from my fetch to reflect in my SearchListControl articlePosts. The problem is onchange results are returned without waiting for fetch to complete so I always get the result from the last onchange. I need a way of updating the inpsector controls SearchListControl articlePosts after my async function has been completed. Any ideas?

import { PanelBody, SelectControl } from '@wordpress/components';
import { SearchListControl  } from '@woocommerce/components';
import { __ } from '@wordpress/i18n';
import { BlockControls, InspectorControls } from '@wordpress/block-editor';
import { ServerSideRender } from '@wordpress/editor';
import { Button, Disabled, Placeholder, Toolbar} from '@wordpress/components';
import { Component, Fragment } from '@wordpress/element';

var articlePosts = [];

async function getArticlesByType(articleType) {
    let response = await fetch('https://somesite.com/wp-json/wp/v2/' + articleType, {
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        method: 'GET',
    });

    return await response.json();
}

class ArticleGridQueryBuilder extends Component {

    getInspectorControls() {

        const { attributes } = this.props;
        const { title, viewAllText, viewAllTextDestination, selectedArticles, articleType, advertId, location } = attributes;

        async function getArticleQueryBuilderData() {

            console.log('START');

            var getArtPosts = await getArticlesByType( articleType );
            var articlePostsByArticleLength = getArtPosts.length;

            var artnewQuery = [];

            for (var i = 0; i < articlePostsByArticleLength; i++) {     
                artnewQuery.push( { id:  getArtPosts[i].id, name: getArtPosts[i].title.rendered } );
            }

            articlePosts = JSON.parse(JSON.stringify(artnewQuery)); 

            console.log(articlePosts);

            console.log('FINISH');

        }

        getArticleQueryBuilderData();

        return (

            <InspectorControls key="inspector">
                <PanelBody
                    title={ __( 'Articles', 'woocommerce' ) }
                    initialOpen={ true }
                >

                    <SearchListControl
                        className="woocommerce-products"
                        list={ articlePosts }
                        selected = { selectedArticles }
                        onChange = { selectedArticles => this.props.setAttributes( { selectedArticles } )}
                    />

                </PanelBody>

                <PanelBody
                    title={ __( 'Article Type', 'woocommerce' ) }
                    initialOpen={ false }
                >

                        <SelectControl
                            value={ articleType }
                            options={ [
                                { label: 'Show All', value: 'showall' },
                                { label: 'News', value: 'news' },
                                { label: 'Feature', value: 'feature' },
                                { label: 'Infographics', value: 'infographics' },
                                { label: 'Opinion', value: 'opinion' },
                                { label: 'Letters', value: 'letters' },
                                { label: 'L&D', value: 'ld' },
                                { label: 'Research', value: 'research' },
                            ] }

                            onChange = { articleType => this.props.setAttributes( { articleType } )}

                        />

                </PanelBody>

            </InspectorControls>

        );
    }
tellthemachines commented 2 years ago

At first glance, it looks like you're populating articlePosts inside getArticleQueryBuilderData which is running asynchronously, so it's likely that getInspectorControls is returning before it's finished running.

Your best is probably to add articlePosts to component state and run the fetch operation inside componentDidMount. Or else if you can use hooks instead of a class component, you could leverage useEffect for the fetching.

tellthemachines commented 2 years ago

I'm going to go ahead and close this issue now.