Perform an API request and list the results

Using restApi you can easily retrieve Deskpro data or external data to populate your App.

Accessing Deskpro data

Let's first start by getting some data from Deskpro api/v2

App.jsx
import React from 'react';
import PropTypes from 'prop-types';
import { Phrase } from '@deskpro/apps-components';
import './styles.css';

class App extends React.Component {
  static propTypes = {
    dpapp: PropTypes.object.isRequired,
    uiProps: PropTypes.shape({
      state: PropTypes.oneOf(['ready', 'loading', 'error', 'inactive']),
      display: PropTypes.oneOf(['collapsed', 'expanded', 'fullscreen']),
      badgeCount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
      badgeVisibility: PropTypes.oneOf(['hidden', 'visible']),
    }).isRequired,
  };

  state = {
    attachments: [],
  };

  componentDidMount() {
    const { dpapp } = this.props;

    const ticketId = dpapp.context.props.object.props.entityId;

    dpapp.restApi.get(`tickets/${ticketId}/attachments`).then(resp => {
      this.setState({
        attachments: resp.body.data
      })
    });
  }

  render() {
    const { attachments } = this.state;
    return (
      <div>
        <h4>Ticket attachments</h4>
        { attachments.map(attachment =>
          <div key={attachment.blob.blob_id}>
            <a href={attachment.blob.download_url}>{attachment.blob.filename}</a>
          </div>
        )}
      </div>
    );
  }
}

export default App;

Here's what we are doing:

We get the current ticket id from the context

App.jsx
const ticketId = dpapp.context.props.object.props.entityId;

Then we use this value to query the API and set the result in the local state.

App.jsx
dpapp.restApi.get(`tickets/${ticketId}/attachments`).then(resp => {
  this.setState({
    attachments: resp.body.data
  })
});

In the render function we loop over the results to display the field we are interested in

App.jsx
{ attachments.map(attachment =>
  <div key={attachment.blob.blob_id}>
    <a href={attachment.blob.download_url}>{attachment.blob.filename}</a>
  </div>
)}

Accessing another API

To request another api we need to use the fetch method

App.jsx
import React from 'react';
import PropTypes from 'prop-types';
import { Phrase } from '@deskpro/apps-components';
import './styles.css';

class App extends React.Component {
  static propTypes = {
    dpapp: PropTypes.object.isRequired,
    uiProps: PropTypes.shape({
      state: PropTypes.oneOf(['ready', 'loading', 'error', 'inactive']),
      display: PropTypes.oneOf(['collapsed', 'expanded', 'fullscreen']),
      badgeCount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
      badgeVisibility: PropTypes.oneOf(['hidden', 'visible']),
    }).isRequired,
  };

  state = {
    users: [],
    loading: true,
  };

  componentDidMount() {
    const { dpapp } = this.props;

    const init = {
      method: 'GET',
      mode: 'cors',
      headers: {},
      cache: 'default'
    };
    dpapp.restApi.fetch('https://reqres.in/api/users', init).then(resp => {
      this.setState({
        users: resp.body.data,
        loading: false
      })
    });
  }

  render() {
    const { loading, users } = this.state;
    return (
      <div>
        { loading ? 
          <Phrase id="loading" />
        ) : (
          users.map(user =>
          <div key={user.id}>
            <img src={user.avatar} width={30} alt="" />
            <span>{user.first_name} {user.last_name}</span>
          </div>
        )}
      </div>
    );
  }
}

export default App;

For this to work you will need to whitelist the external API in your manifest

package.json
"deskpro": {
  "externalApis": [
    "/^https?://([^.]+\\.)*reqres.in/?.*$/"
  ]
}

Here's what we are doing:

We first create the init object describing our request to the fetch method

App.jsx
const init = {
    method: 'GET',
    mode: 'cors',
    headers: {},
    cache: 'default'
};

As before we are querying the external API to get our data and assigning it to the local state.

App.jsx
dpapp.restApi.fetch('https://reqres.in/api/users', init).then(resp => {
  this.setState({
    users: resp.body.data
  })
});

In the render function we loop over the results to display the field we are interested in, but here we are displaying "Loading" as long as we don't have the results

App.jsx
{ loading ? 
  <Phrase id="loading" />
) : (
  users.map(user =>
  <div key={user.id}>
    <img src={user.avatar} width={30} alt="" />
    <span>{user.first_name} {user.last_name}</span>
  </div>
)}

Last updated