Inertia Rails

repository·master·Indexed 22 days ago

https://github.com/inertiajs/inertia-rails

A library that allows developers to build single-page applications using React, Vue, or Svelte while maintaining a traditional Rails development experience with controllers and routes. It eliminates the need for a separate API layer by passing data directly from the server to frontend components as props. Key features include server-side rendering (SSR), partial reloads, deferred props, and native RSpec/Minitest matchers.

Tokens
89K
Snippets
321
Records
434
Agent score
78%

What's inside inertia-rails

  1. Overview of Inertia Rails Starter Kits

    master

    Inertia Rails starter kits provide full-stack scaffolding for building Rails applications with React, Vue, or Svelte frontends. They are designed to be the fastest way to start an Inertia-powered Rails project by pre-configuring the integration between Rails and modern frontend frameworks.

    Key features included in the kits:

    • Inertia Rails & Vite Rails configuration.
    • Frontend Frameworks: React (with TypeScript & shadcn/ui), Vue, or Svelte.
    • Authentication: A built-in user authentication system based on Authentication Zero.
    • Deployment: Kamal support for deployment.
    • SSR: Optional Server-Side Rendering support.
  2. Build forms with the `<Form>` component or `useForm` helper

    master
    Inertia provides two primary ways to build forms in your frontend components: the <Form> component and the useForm helper. Both methods are designed to integrate with your server-side framework's validation and handle form submissions without requiring full page reloads.
  3. Core features of Inertia Rails

    master

    Inertia Rails provides several advanced features for building modern web applications within a Rails monolith:

    • Forms & Validation: Validation errors from Rails flow automatically to your components.
    • Server-side rendering (SSR): Full SSR support for SEO and faster initial paint.
    • Testing: Native-feeling RSpec and Minitest matchers to assert on props and components.
    • Partial reloads: Refresh only specific data instead of full page loads.
    • Shared data: Automatically make data like current_user, flash, or permissions available on every page.
    • Deferred props: Load the page immediately and fetch expensive data in the background with built-in loading states.
    • Rails generators: Scaffold entire CRUD interfaces including controllers and matching components.
    • History encryption: Toggleable encryption for sensitive data in the browser history.
  4. Access form state and methods via Slot Props

    master

    The <Form> component exposes reactive state and helper methods through its default slot. This allows you to react to processing states, display validation errors, and trigger form actions.

    Available properties in the slot object:

    • errors: An object containing validation errors (supports dotted notation for nested fields).
    • hasErrors: Boolean indicating if there are any errors.
    • processing: Boolean indicating if the form is currently being submitted.
    • progress: Progress information for uploads.
    • wasSuccessful: Boolean indicating if the last submission was successful.
    • recentlySuccessful: Boolean indicating if the submission was recently successful.
    • isDirty: Boolean indicating if the form has unsaved changes.
    • defaults: The original default values of the form.
    • setError, clearErrors, resetAndClearErrors: Error management utilities.
    • reset, submit: Form action utilities.
    • recentlySuccessful: Boolean indicating if the submission was recently successful.
    <template>
      <Form
        action="/users"
        method="post"
        #default="{ errors, processing, wasSuccessful, reset }"
      >
        <input type="text" name="name" />
    
        <div v-if="errors.name">{{ errors.name }}</div>
    
        <button type="submit" :disabled="processing">
          {{ processing ? 'Creating...' : 'Create User' }}
        </button>
    
        <div v-if="wasSuccessful">User created successfully!</div>
      </Form>
    </template>
  5. Understand Layout Prop Merge Priority

    master

    Layout props are resolved from multiple sources using the following priority (highest to lowest):

    1. Dynamic props - set via setLayoutProps()
    2. Static props - defined in the persistent layout definition (including callback props)
    3. Defaults - declared as default values on the layout component's props

    Note on Navigation: Dynamic layout props are automatically reset when navigating to a new page (unless preserveState is enabled).

  6. Repopulate form input after validation errors

    master

    You do not need to manually repopulate form data after a validation error in Inertia.

    When a validation error occurs, the server redirects the user back to the form page. By default, Inertia preserves component state for post, put, patch, and delete requests. This means all existing form input data is automatically maintained in the client-side state, so you only need to focus on displaying the errors prop.

  7. Use Dot-Notation for Nested Prop Targeting

    master

    Inertia v3 supports nested prop types (InertiaRails.optional, InertiaRails.defer(), and InertiaRails.merge()) inside closures and arrays.

    On the client side, you can target these nested props using dot-notation in the only and except options of router.reload(), as well as in <Deferred> and <WhenVisible> components.

    Rails Example

    render inertia: {
      auth: -> {
        {
          user: Current.user,
          notifications: InertiaRails.defer { Current.user.unread_notifications }
        }
      }
    }

    Client Example

    // Target the nested notifications prop
    router.reload({ only: ['auth.notifications'] })
    router.reload({ only: ['auth.notifications'] })
  8. Implement Precognition for real-time validation

    master

    The <Form> component supports Precognition, allowing you to trigger server-side validation for specific fields in real-time.

    Key Helpers:

    • validate(fieldName|options): Triggers validation for a field or set of fields. If called with an options object, you can provide onSuccess, onValidationError, onBeforeValidation, and onFinish callbacks. If called with an object containing only, it validates specific fields.
    • invalid(fieldName): Returns true if the field has validation errors.
    • valid(fieldName): Returns true if the field has passed validation.
    • validating: Boolean indicating if a validation request is in progress.
    • touch(fieldName): Marks a field as "touched" without triggering validation. You can then call validate() without arguments to validate all touched fields.
    • touched(fieldName): Checks if a field has been touched.

    Important Notes:

    • Validation requests are automatically debounced (1500ms by default). Use validationTimeout prop to change this.
    • A field only appears valid/invalid once it has changed and a response is received.
    • By default, files are excluded from validation to prevent unnecessary uploads. Use the validateFiles prop to include them.
    <template>
      <Form
        action="/users"
        method="post"
        #default="{ errors, invalid, validate, validating }"
      >
        <label for="name">Name:</label>
        <input id="name" name="name" @change="validate('name')" />
        <p v-if="invalid('name')">{{ errors.name }}</p>
    
        <p v-if="validating">Validating...</p>
    
        <button type="submit">Create User</button>
      </Form>
    </template>
  9. How Inertia replaces the view layer

    master
    Inertia allows you to keep your existing server-side workflow (routing, controllers, middleware, authentication, etc.) while replacing traditional server-side templates (like ERB or Slim) with JavaScript page components. Instead of rendering HTML on the server, your controllers return data that is used to render components in frameworks like React, Vue, or Svelte.
  10. How the 'always' prop works in WhenVisible

    master

    By default, WhenVisible triggers data loading only once when the element becomes visible.

    If you provide the always prop, the component will trigger the data loading every time the element enters the viewport. This is useful for infinite scroll patterns. If a request is already in flight, the component will wait for it to finish before starting a new one if the element remains visible.

    <WhenVisible data="products" always>
      <!-- ... -->
    </WhenVisible>
  11. How validation works in Inertia Rails

    master

    Inertia handles server-side validation errors differently than standard XHR requests. Instead of receiving a 422 Unprocessable Entity response, Inertia expects a standard server-side redirect back to the form page.

    When validation fails, you should redirect the user back to the previous page and flash the validation errors into the session. The Inertia Rails adapter automatically shares these errors with the client-side via the errors prop.

    Inertia determines if a request failed validation by checking the page.props.errors object. If errors are present, the request's onError() callback is triggered instead of onSuccess().

    class UsersController < ApplicationController
      def create
        user = User.new(user_params)
    
        if user.save
          redirect_to users_url
        else
          # Redirect back to the form and share errors via the inertia option
          redirect_to new_user_url, inertia: { errors: user.errors }
        end
      end
    
      private
    
      def user_params
        params.expect(user: [:name, :email])
      end
    end
  12. Handle multiple Head instances and prevent duplicates

    master

    You can use multiple <Head> components (e.g., one in a Layout and one in a Page). While Inertia ensures only one <title> tag is rendered, other tags will stack.

    To prevent duplicate tags (like multiple <meta name="description"> tags), use the head-key property. When a tag has a head-key, Inertia will ensure only one instance of that tag is rendered, allowing page-specific tags to override layout defaults.