When building applications using Inertia, each page in your application typically has its own controller / route and a corresponding JavaScript component.
This allows you to retrieve just the data necessary for that page - no API required. With inertia-server, working with pages is based on the concept
of page definitions created by the definePage function.
Page definitions consist of the component name, and a set of props that will be passed to it.
~/server/inertia.ts
Copy
import { createInertia, prop, mergedProp, deepMergedProp, type PageProps } from 'inertia-server';const homePage = definePage({ component: 'Home', props: { title: prop<string>(), description: prop<string>(), posts: mergedProp<Posts[]>(), tasks: deepMergedProp<Tasks[]>().deferred(), }, // Make sure that the 'user' shared key is available // during render, otherwise it is optional requireShared: ['user'],});export type HomePageProps = PageProps<typeof homePage>;
When handling inertia requests, you can render your page by passing a page context
to the render function. It is created by invoking your page definition with the required props.
Inertia overwrites props with the same name when reloading a page. However, you may need to merge new data with existing data instead.
For example, when implementing a “load more” button for paginated results.Prop merging only works during partial reloads. Full page reloads
will override the props with the new values.
If you want to not only append, but replace some of the existing data, provide a matchOn option.
By sending items with the same key, elements will be replaced, and rest - appended or prepended.
Deep merging was introduced before normal merging had support for prepending and targeting nested paths. In most cases, mergedProp()
with matchOn and its append and prepend methods should be sufficient.
In this case, inertia will try to read page query parameter from your request and use it as the page number. To customise it, you can use the pageName option.
When rendering a page, every prop value can be a literal, or a lazy evaluated function.
It’s up to you which data loading strategy to use. Let’s see how it works on an example.
Copy
const page = definePage({ component: 'Home', props: { foo: prop<string>(), bar: prop<string>().deferred(), },})// Option 1inertia.render(page({ foo: 'foo', bar: () => getBar(),}));// Option 2inertia.render(page({ foo: () => 'foo', bar: getBar(),}));
In both cases, the foo prop will be sent during every page request, but if you define
its value as a function, it will be resolved when inertia needs to parse its value,
not at the moment of the render call. It is especially useful when you work with partial
data requests.Interestingly, the bar prop will not be parsed by inertia on the first request. By default
you should provide a lazy evaluable function to defer execution of your code until it’s needed.
But if you want to, you can provide a literal value at the moment of the render call. It will
not be sent to the client, but it may useful if you want to execute some side effect when a page
is rendered and the prop prepared, no matter whether its loaded or not.
By default, all deferred props get fetched in one request after the initial page is rendered, but you can choose to fetch data in parallel by grouping props together.
In the example above, the teams and roles props will be fetched in one request, while the permissions prop will be fetched in a separate request in parallel. Group names are arbitrary strings and can be anything you choose.On the client side, inertia provides the Deferred component to handle deferred props. It is not required with inertia-server, because we correctly type deferred props as optional, so you can
just check for the value and show a loading state. If you need to
differentiate between the loading state and a potential empty value, use the component though.
When Inertia performs a request, it will determine which data is required and only then will it evaluate the closure. With prop modifiers, you can manually control this behavior.Use optional() method to specify that a prop should never be included unless explicitly requested using the only client option.On the reverse, you can use always() method to specify that a prop should always be included, even in partial reloads.To load a prop on the first request, and then to keep it in the cache, you can use once() method.