|
| 1 | +# Flash Data |
| 2 | + |
| 3 | +@available_since rails=master core=2.3.3 |
| 4 | + |
| 5 | +Sometimes you may wish to send one-time data to your frontend that shouldn't reappear when users navigate through browser history. Unlike regular props, flash data isn't persisted in history state, making it ideal for success messages, newly created IDs, or other temporary values. |
| 6 | + |
| 7 | +## Flashing Data |
| 8 | + |
| 9 | +You may flash data using the `inertia_flash` controller method. |
| 10 | + |
| 11 | +```ruby |
| 12 | +class UsersController < ApplicationController |
| 13 | + def edit |
| 14 | + user = User.new(user_params) |
| 15 | + |
| 16 | + if user.save |
| 17 | + inertia_flash[:message] = 'User created successfully!' |
| 18 | + |
| 19 | + redirect_to users_url |
| 20 | + else |
| 21 | + redirect_to new_user_url, inertia: { errors: user.errors } |
| 22 | + end |
| 23 | + end |
| 24 | +end |
| 25 | +``` |
| 26 | + |
| 27 | +Passing props to `redirect_to` is also supported. |
| 28 | + |
| 29 | +```ruby |
| 30 | +redirect_to users_url, inertia: { flash: { new_user_id: user.id } } |
| 31 | +``` |
| 32 | + |
| 33 | +Flash data is scoped to the current request. The middleware automatically persists it to the session when redirecting. After the flash data is sent to the client, it is cleared and will not appear in subsequent requests. |
| 34 | + |
| 35 | +## Accessing Flash Data |
| 36 | + |
| 37 | +Flash data is available on `page.flash`. You may also listen for the global `flash` event or use the `onFlash` callback. |
| 38 | + |
| 39 | +:::tabs key:frameworks |
| 40 | + |
| 41 | +== Vue |
| 42 | + |
| 43 | +```vue |
| 44 | +<script setup> |
| 45 | +import { usePage } from '@inertiajs/vue3' |
| 46 | +
|
| 47 | +const page = usePage() |
| 48 | +</script> |
| 49 | +
|
| 50 | +<template> |
| 51 | + <div v-if="page.flash.toast" class="toast"> |
| 52 | + {{ page.flash.toast.message }} |
| 53 | + </div> |
| 54 | +</template> |
| 55 | +``` |
| 56 | + |
| 57 | +== React |
| 58 | + |
| 59 | +```jsx |
| 60 | +import { usePage } from '@inertiajs/react' |
| 61 | + |
| 62 | +export default function Layout({ children }) { |
| 63 | + const { flash } = usePage() |
| 64 | + |
| 65 | + return ( |
| 66 | + <> |
| 67 | + {flash.toast && <div className="toast">{flash.toast.message}</div>} |
| 68 | + {children} |
| 69 | + </> |
| 70 | + ) |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +== Svelte 4|Svelte 5 |
| 75 | + |
| 76 | +```svelte |
| 77 | +<script> |
| 78 | + import { page } from '@inertiajs/svelte' |
| 79 | +</script> |
| 80 | +
|
| 81 | +{#if $page.flash.toast} |
| 82 | + <div class="toast">{$page.flash.toast.message}</div> |
| 83 | +{/if} |
| 84 | +``` |
| 85 | + |
| 86 | +::: |
| 87 | + |
| 88 | +## The onFlash Callback |
| 89 | + |
| 90 | +You may use the `onFlash` callback to handle flash data when making requests. |
| 91 | + |
| 92 | +:::tabs key:frameworks |
| 93 | + |
| 94 | +== Vue |
| 95 | + |
| 96 | +```js |
| 97 | +import { router } from '@inertiajs/vue3' |
| 98 | + |
| 99 | +router.post('/users', data, { |
| 100 | + onFlash: ({ newUserId }) => { |
| 101 | + form.userId = newUserId |
| 102 | + }, |
| 103 | +}) |
| 104 | +``` |
| 105 | + |
| 106 | +== React |
| 107 | + |
| 108 | +```js |
| 109 | +import { router } from '@inertiajs/react' |
| 110 | + |
| 111 | +router.post('/users', data, { |
| 112 | + onFlash: ({ newUserId }) => { |
| 113 | + form.userId = newUserId |
| 114 | + }, |
| 115 | +}) |
| 116 | +``` |
| 117 | + |
| 118 | +== Svelte |
| 119 | + |
| 120 | +```js |
| 121 | +import { router } from '@inertiajs/svelte' |
| 122 | + |
| 123 | +router.post('/users', data, { |
| 124 | + onFlash: ({ newUserId }) => { |
| 125 | + form.userId = newUserId |
| 126 | + }, |
| 127 | +}) |
| 128 | +``` |
| 129 | + |
| 130 | +::: |
| 131 | + |
| 132 | +## Global Flash Event |
| 133 | + |
| 134 | +You may use the global `flash` event to handle flash data in a central location, such as a layout component. For more information on events, see the [events documentation](/v2/advanced/events). |
| 135 | + |
| 136 | +:::tabs key:frameworks |
| 137 | + |
| 138 | +== Vue |
| 139 | + |
| 140 | +```js |
| 141 | +import { router } from '@inertiajs/vue3' |
| 142 | + |
| 143 | +router.on('flash', (event) => { |
| 144 | + if (event.detail.flash.toast) { |
| 145 | + showToast(event.detail.flash.toast) |
| 146 | + } |
| 147 | +}) |
| 148 | +``` |
| 149 | + |
| 150 | +== React |
| 151 | + |
| 152 | +```js |
| 153 | +import { router } from '@inertiajs/react' |
| 154 | + |
| 155 | +router.on('flash', (event) => { |
| 156 | + if (event.detail.flash.toast) { |
| 157 | + showToast(event.detail.flash.toast) |
| 158 | + } |
| 159 | +}) |
| 160 | +``` |
| 161 | + |
| 162 | +== Svelte 4|Svelte 5 |
| 163 | + |
| 164 | +```js |
| 165 | +import { router } from '@inertiajs/svelte' |
| 166 | + |
| 167 | +router.on('flash', (event) => { |
| 168 | + if (event.detail.flash.toast) { |
| 169 | + showToast(event.detail.flash.toast) |
| 170 | + } |
| 171 | +}) |
| 172 | +``` |
| 173 | + |
| 174 | +::: |
| 175 | + |
| 176 | +Native browser events are also supported. |
| 177 | + |
| 178 | +:::tabs key:frameworks |
| 179 | + |
| 180 | +== Vue |
| 181 | + |
| 182 | +```js Vue icon="vuejs" |
| 183 | +document.addEventListener('inertia:flash', (event) => { |
| 184 | + console.log(event.detail.flash) |
| 185 | +}) |
| 186 | +``` |
| 187 | + |
| 188 | +== React |
| 189 | + |
| 190 | +```js |
| 191 | +document.addEventListener('inertia:flash', (event) => { |
| 192 | + console.log(event.detail.flash) |
| 193 | +}) |
| 194 | +``` |
| 195 | + |
| 196 | +== Svelte 4|Svelte 5 |
| 197 | + |
| 198 | +```js |
| 199 | +document.addEventListener('inertia:flash', (event) => { |
| 200 | + console.log(event.detail.flash) |
| 201 | +}) |
| 202 | +``` |
| 203 | + |
| 204 | +::: |
| 205 | + |
| 206 | +The `flash` event is not cancelable. During [partial reloads](/guide/partial-reloads), it only fires if the flash data has changed. |
| 207 | + |
| 208 | +## Client-Side Flash |
| 209 | + |
| 210 | +You may set flash data on the client without a server request using the `router.flash()` method. Values are merged with existing flash data. |
| 211 | + |
| 212 | +:::tabs key:frameworks |
| 213 | + |
| 214 | +== Vue |
| 215 | + |
| 216 | +```js |
| 217 | +import { router } from '@inertiajs/vue3' |
| 218 | + |
| 219 | +router.flash('foo', 'bar') |
| 220 | +router.flash({ foo: 'bar' }) |
| 221 | +``` |
| 222 | + |
| 223 | +== React |
| 224 | + |
| 225 | +```js |
| 226 | +import { router } from '@inertiajs/react' |
| 227 | + |
| 228 | +router.flash('foo', 'bar') |
| 229 | +router.flash({ foo: 'bar' }) |
| 230 | +``` |
| 231 | + |
| 232 | +== Svelte 4|Svelte 5 |
| 233 | + |
| 234 | +```js |
| 235 | +import { router } from '@inertiajs/svelte' |
| 236 | + |
| 237 | +router.flash('foo', 'bar') |
| 238 | +router.flash({ foo: 'bar' }) |
| 239 | +``` |
| 240 | + |
| 241 | +::: |
| 242 | + |
| 243 | +A callback may also be passed to access the current flash data or replace it entirely. |
| 244 | + |
| 245 | +:::tabs key:frameworks |
| 246 | + |
| 247 | +== Vue |
| 248 | + |
| 249 | +```js |
| 250 | +import { router } from '@inertiajs/vue3' |
| 251 | + |
| 252 | +router.flash((current) => ({ ...current, bar: 'baz' })) |
| 253 | +router.flash(() => ({})) |
| 254 | +``` |
| 255 | + |
| 256 | +== React |
| 257 | + |
| 258 | +```js |
| 259 | +import { router } from '@inertiajs/react' |
| 260 | + |
| 261 | +router.flash((current) => ({ ...current, bar: 'baz' })) |
| 262 | +router.flash(() => ({})) |
| 263 | +``` |
| 264 | + |
| 265 | +== Svelte 4|Svelte 5 |
| 266 | + |
| 267 | +```js |
| 268 | +import { router } from '@inertiajs/svelte' |
| 269 | + |
| 270 | +router.flash((current) => ({ ...current, bar: 'baz' })) |
| 271 | +router.flash(() => ({})) |
| 272 | +``` |
| 273 | + |
| 274 | +::: |
| 275 | + |
| 276 | +## TypeScript |
| 277 | + |
| 278 | +You may configure the flash data type globally using TypeScript's declaration merging. |
| 279 | + |
| 280 | +```ts |
| 281 | +// global.d.ts |
| 282 | +declare module '@inertiajs/core' { |
| 283 | + export interface InertiaConfig { |
| 284 | + flashDataType: { |
| 285 | + toast?: { |
| 286 | + type: 'success' | 'error' |
| 287 | + message: string |
| 288 | + } |
| 289 | + } |
| 290 | + } |
| 291 | +} |
| 292 | +``` |
| 293 | + |
| 294 | +With this configuration, `page.flash.toast` will be properly typed as `{ type: "success" | "error"; message: string } | undefined`. |
0 commit comments