I'm trying to use fetch to grab information from a 3rd party API which is rate-limited. Instead of doing the API on the front-end I'm trying to use fetch to do the API call in the edit function. I've seemingly have the fetch working, but I can't seem to save the data. Might someone suggest where I'm going wrong?

Attributes look like:

    attributes: {
    url: {
        type: 'string',
        selector: '.o_microlink',
        attribute: 'href',
        default: '',
    },
    title: {
        type: 'string',
        selector: '.o_microlink',
        default: '',
    },
}

Edit function looks like:

edit: props => {
    const onChangeURL = async value => {
        const response = await fetch( `https://api.microlink.io?url=${ value }`, {
            cache: 'no-cache',
            headers: {
                'user-agent': 'WP Block',
                'content-type': 'application/json'
              },
            method: 'GET', 
            redirect: 'follow', 
            referrer: 'no-referrer', 
        }).then(
            returned => {
                if (returned.ok) return returned;
                throw new Error('Network response was not ok.');
            }
        );
        let data = await response.json();
        data = data.data;

        props.setAttributes( { url: value } );
        props.setAttributes( { title: data.title} );
    };
    return <div className={ props.className }>
            <RichText
                tagName="div"
                placeholder={ __( 'Add URL here.' ) }
                value={ props.attributes.url }
                onChange={ onChangeURL }
            />
            { ! props.attributes.title ? __( 'Add URL' ) : <div> { props.attributes.title } </div> }
            </div>;
}

Save function is pretty standard:

save: props => {
    return (
        <div className={ [props.className, 'o_microlink'].join( ' ' ) }>
            <a href={ props.url}> { props.title } </a>
        </div>
    );
}
  • What does "not having any luck" mean? What specifically isn't working? Are you catching an error? Is there something wrong with the response? Is the request not being made? – Jacob Peattie Apr 4 at 1:39
  • The error isn't occurring, as far as I can tell. Either the request is not being made successfully or the function is just not returning how I expect. – jshwlkr Apr 4 at 14:05
  • I'm almost positive this is a asynchronous function in a synchronous one issue. Which is something I haven't dealt with enough to know how to solve. – jshwlkr Apr 4 at 16:04
  • I haven't used the fetch API before, but this looks wrong to me: https://api.microlink.io?url= ${ value }. Should that be in back-ticks? Is the $ supposed to be PHP? – Jacob Peattie Apr 4 at 16:08
  • No that's an ES6 template string (developers.google.com/web/updates/2015/01/ES6-Template-Strings). – jshwlkr Apr 4 at 16:21
up vote 2 down vote accepted

Well, I figured it out. Though my solution is probably far from elegant (I'm not making concessions for timeouts or usability/accessibility). My problem was mostly overzealous configuration, copy and paste errors, and needing to apply async/await keywords.

Attributes look like this:

attributes: {
    url: {
        source: 'attribute',
        type: 'string',
        selector: '.o_microlink',
        attribute: 'href',
    },
    title: {
        type: 'string',
        source: 'text',
        selector: '.o_microlink',
    }

The edit function looks like this:

edit: ({ attributes, setAttributes, className })  => {

    const onChangeURL = async value => {

        const response = await fetch( `https://api.microlink.io?url=${ value }`, {
            cache: 'no-cache',
            headers: {
                'user-agent': 'WP Block',
                'content-type': 'application/json'
              },
            method: 'GET',
            redirect: 'follow', 
            referrer: 'no-referrer', 
        })
        .then(
            returned => {
                if (returned.ok) return returned;
                throw new Error('Network response was not ok.');
            }
        );

        let data = await response.json();
        data = data.data;

        setAttributes( { url: value[0] } );
        setAttributes( { title: data.title} );
    };

    return <div className={className}>
                <RichText
                    tagName="div"
                    placeholder={__('Add URL here.')}
                    value={attributes.url}
                    onChange={onChangeURL}
                />
                {!attributes.title ? __('Add URL') : <div> {attributes.title} </div>}
             </div>;

}

The notable requirement is the async keyword on the arrow function and the two await keywords on the assignments. (I'm not catching the error here or setting the user-agent to anything useful.) The url value in onChangeURL is being set as an array of one item and I'm not sure why.

And the save function:

save: ({ attributes, className }) => {
    return <div className={ className }>
            <a className="o_microlink" href={ attributes.url }> { attributes.title } </a>
        </div>;
}

Which is pretty standard but I had put the custom class in the wrong place.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.