Partial Reloads with InertiaJS

Dan Pastori avatar
Dan Pastori January 20th, 2024

Lately, I’ve fallen in love with InertiaJS. After the 1.0 release and it’s stability improvements, the developer experience is top notch. I feel like I can quickly whip together a stable, functioning app in no time. I get the power of Vue 3 for a beautiful UI, and the beautiful backend of Laravel. In this blog post, we will cover one of my favorite features, partial reloads with InertiaJS.

What are partial reloads?

Partial reloads are when you load only the data that’s needed when it’s requested. What does that mean? Let’s say I initially load a page with a paginated list of transaction resources. It starts at page 1 and goes to page 15. Along with the page load, initially, I load the account, the user, and some state data. When I want to go to the next paginated page of transactions, I only want to load page 2. Not the other resources that were initially loaded.

InertiaJS makes this easy. It’s done through partial reloads. I’ll be honest, when I first started using InertiaJS, it took me awhile to figure out how to load small pieces of data. The small snippet at the end of the partial reload section under the Lazy Data Evaluation heading really tied it all together. Once I got the concept, I felt it was the missing link to build extremely powerful InertiaJS applications.

We will go through a real life example in this blog post. If you’d like to see all the tricks we do with InertiaJS, check out Financial Freedom. The whole app is written in InertiaJS + Vue 3 + Laravel and is 100% Open Source!

How to Set Up Partial Reloads with InertiaJS

To get the most out of your partial reloads, you will have to coordinate what you need on both the frontend and the backend of your application. In the code samples, we will be using Vue 3 for the frontend and obviously Laravel for the backend. The code will work the same if you are using React as well.

We will be going through loading up a paginated financial institution resource in this example. You can see this in the context of a full app when you check out Financial Freedom.

Initializing Your InertiaJS Page

The first part is to determine what data you want loaded initially and reloaded. There’s a small code snippet at the end of the docs on partial reloads that explains how to set this up:

return Inertia::render('Users/Index', [
    // ALWAYS included on first visit...
    // OPTIONALLY included on partial reloads...
    // ALWAYS evaluated...
    'users' => User::get(),

    // ALWAYS included on first visit...
    // OPTIONALLY included on partial reloads...
    // ONLY evaluated when needed...
    'users' => fn () => User::get(),

    // NEVER included on first visit...
    // OPTIONALLY included on partial reloads...
    // ONLY evaluated when needed...
    'users' => Inertia::lazy(fn () => User::get()),
]);

This is literally the key to making this work. Let’s say we load the following resources on the financial institutions page:

  • Financial Institutions
  • Page Group (simple string that shows where we are in the app for navigation).

I find myself using the second example in the code snippet most often. My rule of thumb is simply, if it queries the database and we don’t need it on certain reloads, don’t evaluate it every time. This saves query time dramatically!

Setting Up Our Page

Here’s how I would set up our page using the resources listed above:

return Inertia::render('Settings/Institutions/Index', [
    'group' => 'settings',
    'institutions' => fn () => Institution::paginate(),
]);

Since the group is simply a string, I evaluate and return it every time. The institutions should be loaded initially on the page load which will load the first batch. Then it should be evaluated if requested for a partial reload. This is all we need to do to set this up on the server side. When we make our partial reload request, we can request only to load the institutions, saving a TON of server resources by isolating our database queries!

Making a Partial Reload Request

Now that we have our page initially set up, let’s set up our methods to work with the paginated institutions resource:

const institutions = computed( () => usePage().props.institutions );
const url = ref('/settings/institutions');
const loading = ref(false);

const previous = () => {
    if( institutions.value.prev_page_url == null ){
        return;
    }

    url.value = institutions.value.prev_page_url;
    getInstitutions();
}

const next = () => {
    if( institutions.value.next_page_url == null ){
        return;
    }

    url.value = institutions.value.next_page_url;
    getInstitutions();
}

const toPage = ( page ) => {
    url.value = page;
    getInstitutions();
}

const getInstitutions = () => {
    loading.value = true;

    let params = buildParams();

    router.visit(url.value, {
        only: ['institutions'],
        data: params,
        preserveScroll: true,
        preserveState: true,
        onSuccess: () => {
            loading.value = false
        }
    })
}

const buildParams = () => {
    let params = {};

    return params;
}

Before we dive into this, let’s make sure we include the router object:

import { router } from '@inertiajs/vue3';

Diving into our paginated code

Alright, let’s dive in. First, remember we are using the paginated resource method from Laravel.

Right away, I set up url to be the initial URL of the page with no ?page=X parameter:

const url = ref('/settings/institutions');

With a Laravel paginated resource, we get the “next” and “prev” links. I simply build two methods that handle clicks on these links. We then set the url variable defined to be the URL of those links so when we do our partial reload. You could also just use these links and actually navigate to the page itself. However, for the sake of example and if you want to modify the query params, keep reading.

The same works for jumping pages with the toPage() method. Laravel returns an array of pages you can jump to. All these methods do is set our url variable with what we are looking for. Then we call the getInstitutions() method to perform our partial reload. Since the URL is paginated, it simply appends the ?page=X parameter to the end of our current URL. This fulfills the requirement within InertiaJS of a partial reload can only be on the current page.

Performing our Partial Reload

Now that we have our URL being set with the ?page=X parameter, we can perform our partial reload:

const getInstitutions = () => {
    loading.value = true;

    let params = buildParams();

    router.visit(url.value, {
        only: ['institutions'],
        data: params,
        preserveScroll: true,
        preserveState: true,
        onSuccess: () => {
            loading.value = false
        }
    })
}

What this does is make a call to the InertiaJS router object to the .visit method. You could also use the .reload shortcut method as well. You just would have to handle the page=X query parameter through the data: params instead of the URL provided by Laravel.

What makes this work is we have the only: ['institutions'] option being passed. Since we have a call back method on our server loading the institutions variable, this will be evaluated. Let’s say we didn’t have that callback and we intended to load something else. The institutions would always be evaluated making an unnecessary database query!

In this instance, it works great because we want the next page of financial institutions. You can also pass additional query parameters to build your institutions query on the Laravel side. That’s where the data: params comes in. That’s out of scope of this example, but you could pass query terms, or filters and really make this partial reload dynamic!

Conclusion

Understanding partial reloads is essential to making your InertiaJS app function. It’s also a huge piece of developer experience provided by InertiaJS. If you want to see a full app we’ve written in InertiaJS, check out Financial Freedom. Also, feel free to reach out on X (Formerly Twitter) (@danpastori) if you have any InertiaJS, Laravel or Vue 3 questions!

Support Future Content

Building Multi-Platform Browser Extensions Book Cover

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book on building browser extensions!

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.