2

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>
    );
}
5
  • 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? Commented Apr 4, 2018 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
    Commented Apr 4, 2018 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
    Commented Apr 4, 2018 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? Commented Apr 4, 2018 at 16:08
  • No that's an ES6 template string (developers.google.com/web/updates/2015/01/ES6-Template-Strings).
    – jshwlkr
    Commented Apr 4, 2018 at 16:21

1 Answer 1

6

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

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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