Dynamic API Requests with Nuxt 3
Part 6 of 9 in Upgrading Nuxt 2 to Nuxt 3After your user interacts with your page, it can be necessary to refresh your data. A few examples of when to refresh data is when you need to filter API resources or paginate data.
With Nuxt 3, these dynamic API requests can be structured in a reactive manner. When the query parameters change, the API request is automatically called allowing you to simply re-render the data. In Nuxt 2, this approach was done by wrapping the $axios
plugin and calling a method to refresh the data. In Nuxt 3, we can compute a query string and when it changes, the new data will be fetched. Let’s get started!
Gettings Started
Let’s say we are using our /api/v1/cafes
endpoint in ROAST. This endpoint allows you to search, paginate, and filter by brew methods through an API request. On our search page, we can set these filters and reload the data without reloading the entire page. This is the scenario we are going to step through in Nuxt 2 vs Nuxt 3 because it’s slightly different.
Step 1: Dynamic API Requests in Nuxt 2
Let’s take a look at a quick example of how to make a dynamic API request with Nuxt 2:
data: {
return {
search: '',
brew_methods: [],
page: 1,
cafes: []
}
},
methods: {
async searchCafes( page = 1 ) {
let params = buildSearchCafes( page );
const cafes = await this.$axios.$get('https://api.roastandbrew.coffee/api/v1/cafes', {
params: params
});
this.cafes = cafes
},
buildSearchCafes( page ){
let searchParams = {};
// Pagination
searchParams.page = page;
searchParams.take = 12;
if( this.search != '' ){
searchParams.search = encodeURIComponent( this.search );
}
if( this.brew_methods.length > 0 ){
searchParams.brew_methods = encodeURIComponent( this.brew_methods.join(',') );
}
return searchParams;
}
}
There are 3 sections to this example.
Defining Data
First, we have the data
. The data
contains all of the different variables the user can use to load what they need from the API endpoint. In reality, there are a lot more, but for this example, we have a search
string, brew_methods
array, page
for pagination, and cafes
array used to display the data.
Building the Query Parameters
Next, we have the buildSearchCafes( page )
method. This method, simply takes what the user has selected, converts the selections to a JSON object, and returns them. We use these query parameters in our request to our API endpoint in the next step.
Making our Dynamic API Request
Finally, we make our API request. In Nuxt 2, you had a few options. I always used the $axios
module since it was easy to customize. You could use fetch or the $http
plugin as well. Whatever way you chose to do it, you needed to make an API request with the query parameters. Once you got the data back from the API, you could set it to your local cafes
data array. Vue would then reactively display the updates.
When the user clicked a pagination button such as previous, a number, or next, we’d re-request the data with what the user selected. We’d also call the searchCafes()
method if the user searches or filters the results. This process allows the user to refresh the data without leaving the page. In Nuxt 3, the process is similar, but a little more reactive.
Step 2: Dynamic API Requests in Nuxt 3
When we build these dynamic API requests in Nuxt 3, we will be focusing solely on watching for changes to our filter variables. This will trigger our watched query string, which will in-turn update the data. Let’s take a look:
const search = useState('search', '');
const brewMethods = useState('brewMethods', []);
const page = useState('page', 1);
const queryString = computed(() => {
let values = '?page='+page.value+'&take=12';
values += search.value != '' ? '&search='+search.value : '';
values += brewMethods.value.length > 0 ? '&brew_methods='+brewMethods.value.join(',') : '';
return values;
});
const { data:cafes, pending, refresh } = await useLazyAsyncData(
'cafes',
() => $fetch( `https://api.roastandbrew.coffee/cafes${queryString.value}`)
)
// When query string changes, refresh
watch(() => queryString.value, () => refresh() );
Before we break this functionality down and the differences, note that you should use this in a <script setup>
tag or setup()
method with Vue 3. Now this looks entirely different, but the functionality is the same. Instead of calling a method that refreshes our API, we watch for changes on a dynamic query string.
Defining the State
First, we define the state that we need within our component. We have a search
string, brewMethods
array, and page
that keeps track of the pagination. We didn’t include our cafes
here, because we set that variable up with asyncData
which we will discuss soon.
Building our Query String
Next, we have our computed queryString
. This variable reacts and updates when one of the dependent variables changes. If you break down the method, whenever the page
, search
or brewMethods
gets updated, we dynamically build the query string and return it. This is extremely powerful and you will see why shortly.
Making our Dynamic API Request
To define our cafes
variable which is used to render the page, we use the useLazyAsyncData()
composable. This composable allows us to decouple the data:cafes
, pending
, and refresh
method. All are extremely important. The data:cafes
defines the variable we use to load our cafes from our API request. To show whether the request has completed or not, we can use the pending
variable. It will be set to true
or false
depending on whether the request is loading or not. Finally, we have a refresh()
method. This will re-send our API request if we need to refresh the data stored in the cafes
variable. This is where the magic happens!
Watching for Changes
The last line of our code ties everything together:
watch(() => queryString.value, () => refresh() );
What this little snippet does is watch the value of our query string. When the query string changes after the user adjusts a search parameter, pagination page, or filter, we call the refresh()
method. Since we append the queryString
to our API request, when we refresh after a change, the new query string will be sent to the API. This is how we update our data!
So there’s actually another way to do this using Watch Sources. Feel free to skip ahead to Advanced Data Fetching with Nuxt 3 to learn more.
Conclusion
Both Nuxt 2 and Nuxt 3 allow you to easily build dynamic api requests into your application. Even though the structure and syntax is different, the functionality is the same. When migrating from Nuxt 2 to Nuxt 3, these changes may be cumbersome but as you finish your migration it all ties together. You get the speed and updated functionality of Nuxt 3 along with maintaining the existing features in your app.
If you want to see a more cohesive approach to how this works, we do have a book! In the book, we go through multiple API requests, some dynamic, some more static and how they play into the app as a whole.
If there are any questions, feel free to reach out on Twitter (@danpastori) or on our community forum!