Skip to content

Once Props ​

Once props are cached on the client and skipped during subsequent navigations. This is useful for expensive data that doesn't change often, like user profiles or permission lists.

Basic Usage ​

Use sails.inertia.once() to create a cached prop:

js
sails.inertia.share(
  'loggedInUser',
  sails.inertia.once(async () => {
    return await User.findOne({ id: req.session.userId })
  })
)

The callback is only executed on the first page load. On subsequent navigations, the client uses its cached version.

Chainable Methods ​

.as(key) ​

Set a custom cache key:

js
sails.inertia.once(() => fetchPermissions()).as('user-permissions')

.until(seconds) ​

Set a TTL (time-to-live) expiration:

js
sails.inertia.once(() => fetchCountries()).until(3600) // Cache for 1 hour

.fresh(condition) ​

Force refresh when a condition is true:

js
sails.inertia.once(() => fetchUser()).fresh(req.query.refresh === 'true')

Combining Methods ​

Methods are chainable:

js
sails.inertia
  .once(() => fetchPermissions())
  .as('user-permissions')
  .until(3600)
  .fresh(req.query.refresh === 'true')

Shorthand: shareOnce ​

shareOnce() is a shorthand for share() + once():

js
// These are equivalent:
sails.inertia.share(
  'countries',
  sails.inertia.once(() => Country.find())
)
sails.inertia.shareOnce('countries', () => Country.find())

Refreshing from Actions ​

Use sails.inertia.refreshOnce() to invalidate cached props after data changes:

js
// api/controllers/profile/update-profile.js
module.exports = {
  inputs: {
    fullName: { type: 'string', required: true }
  },

  exits: {
    success: { responseType: 'inertiaRedirect' }
  },

  fn: async function ({ fullName }) {
    await User.updateOne({ id: this.req.session.userId }).set({ fullName })

    // Force client to re-fetch the cached user
    sails.inertia.refreshOnce('loggedInUser')
    sails.inertia.flash('success', 'Profile updated!')

    return sails.inertia.back('/profile')
  }
}

Refresh multiple keys at once:

js
sails.inertia.refreshOnce(['loggedInUser', 'teams', 'currentTeam'])

Custom Hook Example ​

A complete example sharing user data with caching:

js
// api/hooks/custom/index.js
module.exports = function defineCustomHook(sails) {
  return {
    routes: {
      before: {
        'GET /*': {
          skipAssets: true,
          fn: async function (req, res, next) {
            if (req.session.userId) {
              sails.inertia.share(
                'loggedInUser',
                sails.inertia.once(async () => {
                  return await User.findOne({ id: req.session.userId }).select([
                    'id',
                    'email',
                    'fullName',
                    'avatarUrl'
                  ])
                })
              )
            }
            return next()
          }
        }
      }
    }
  }
}

When to Use Once Props ​

ScenarioUse once()
User profile dataYes
Permission listsYes
Reference data (countries, categories)Yes
Page-specific dataNo
Frequently changing dataNo

Once props shine for data that's:

  • Expensive to fetch
  • Used across multiple pages
  • Changes infrequently

For data that changes often, use regular props or Deferred Props.

All open source projects are released under the MIT License.