---
title: AJAX
path: /v5/ajax/
index: 11
---
import Ajax from '../../components/examples/Ajax';
Initiating AJAX requests is facilitated by lifecycle hooks. This allows you to
do very powerful things. For example, let's say you wanted to show a new image
inside a tooltip each time it gets shown:
Hover for a new image
Let's walk through a little tutorial to learn how to do this.
First, let's setup our HTML:
```html
```
Now, let's add some JavaScript:
```js
tippy('#ajax-tippy', {
content: 'Loading...',
// This prop is recommended if your tooltip changes size while showing
flipOnUpdate: true,
});
```
Here's the result so far (nothing happens yet!):
To initiate the AJAX request every time the tippy shows, use the `onShow`
lifecycle:
```js
tippy('#ajax-tippy', {
content: 'Loading...',
flipOnUpdate: true,
onShow(instance) {
// Code here is executed every time the tippy shows
},
});
```
Using `fetch`, we can fetch a random image from an Unsplash API:
```js
tippy('#ajax-tippy', {
// ...
onShow(instance) {
fetch('https://unsplash.it/200/?random')
.then((response) => response.blob())
.then((blob) => {
// Convert the blob into a URL
const url = URL.createObjectURL(blob);
// Create an image
const image = new Image();
image.width = 200;
image.height = 200;
image.style.display = 'block';
image.src = url;
// Update the tippy content with the image
instance.setContent(image);
})
.catch((error) => {
// Fallback if the network request failed
instance.setContent(`Request failed. ${error}`);
});
},
});
```
There are currently two problems with this:
- When the tippy is hidden, it doesn't reset back to `Loading...`
- If you quickly hover in and out of the tippy, it initiates many different
requests and each image rapidly replaces the old one as each request finishes
The first one can be solved by using the `onHidden` lifecycle, which is executed
once the tippy fully transitions out and is unmounted from the DOM:
```js
tippy('#ajax-tippy', {
// ...
onHidden(instance) {
instance.setContent('Loading...');
},
});
```
The second one requires some state:
```js
tippy('#ajax-tippy', {
// ...
onCreate(instance) {
// Setup our own custom state properties
instance._isFetching = false;
instance._src = null;
instance._error = null;
},
onShow(instance) {
if (instance._isFetching || instance._src || instance._error) {
return;
}
instance._isFetching = true;
fetch('https://unsplash.it/200/?random')
.then((response) => response.blob())
.then((blob) => {
const src = URL.createObjectURL(blob);
instance._src = src;
// ...
})
.catch((error) => {
instance._error = error;
instance.setContent(`Request failed. ${error}`);
})
.finally(() => {
instance._isFetching = false;
});
},
onHidden(instance) {
instance.setContent('Loading...');
// Unset these properties so new network requests can be initiated
instance._src = null;
instance._error = null;
},
});
```
Currently, the image instantly replaces the `Loading...` text without any smooth
transition. How do we make it so the tooltip smoothly transitions in height?
[See the Animations page for details](../animations/#dimensions-transition).