Skip to main content

ReactOnRails JavaScript API

CSRF protection

Rails has built-in protection for Cross-Site Request Forgery (CSRF), see Rails Documentation. To nicely utilize this feature in JavaScript requests, React on Rails provides two helpers that can be used as following for POST, PUT or DELETE requests:

import ReactOnRails from 'react-on-rails';

// reads from DOM csrf token generated by Rails in <%= csrf_meta_tags %>
csrfToken = ReactOnRails.authenticityToken();

// compose Rails specific request header as following { X-CSRF-Token: csrfToken, X-Requested-With: XMLHttpRequest }
header = ReactOnRails.authenticityHeaders(otherHeader);

If you are using jquery-ujs for AJAX calls, then these helpers are not needed because the jquery-ujs library updates header automatically, see jquery-ujs documentation.

API

The best source of docs is the interface ReactOnRails in types/index.ts. Here's a quick summary, last updated for React on Rails 17.0.

/**
* Main entry point to using the react-on-rails NPM package. This is how Rails will be able to
* find your components for rendering.
*
* Component detection: React on Rails distinguishes between component types by parameter count:
* - 0-1 params: Regular React component (function or class)
* - 2 params, or any function with `.renderFunction = true`: Render-Function — called with (props, railsContext),
* returns a React component, `{ renderedHtml }` object, or Promise (Pro Node renderer only)
* - 3 params: Renderer function — called with (props, railsContext, domNodeId),
* responsible for calling ReactDOM.render/hydrate directly (client-only).
* May optionally return a `{ teardown }` wrapper (or a promise resolving to one); React on Rails
* runs it on Turbo/Turbolinks navigation or same-id node replacement to unmount the renderer's root
* instead of leaking it. See the view-helpers renderer-function docs.
*
* Render-Functions can return:
* - A React component (function or class) — used with `react_component`
* - `{ renderedHtml: string }` — raw HTML string, used with `react_component`
* - `{ renderedHtml: ReactElement }` — server rendering only, used with `react_component`
* - `{ renderedHtml: { componentHtml, ...otherKeys } }` — used with `react_component_hash`
* - `{ renderedHtml, clientProps }` — clientProps are merged into client hydration props
* - `{ redirectLocation, routeError }` — legacy (React Router v3/v4), see render-functions docs
*
* @param components (key is component name, value is component)
*/
register(components);

/**
* Allows registration of store generators for legacy or advanced pages where multiple React
* roots on one Rails view share a Redux store. Store generators receive props and railsContext,
* then return a store. Note that the setStore API is different in that it's the actual store
* hydrated with props.
* @param stores (key is store name, value is the store generator)
*/
registerStoreGenerators(storesGenerators);

/**
* Allows retrieval of the store by name. This store will be hydrated by any Rails form props.
* Pass optional param throwIfMissing = false if you want to use this call to get back undefined if
* the store with name is not hydrated.
* @param name
* @param throwIfMissing Defaults to true. Set to false to have this call return undefined if
* there is no store with the given name.
* @returns Redux Store, possibly hydrated
*/
getStore(name, (throwIfMissing = true));

/**
* **Pro only.** Get a store by name, or wait for it to be registered and
* hydrated. Returns a Promise that resolves with the store instance once
* available. Use when a non-React piece of code (e.g., a TanStack Router
* loader or middleware) needs to read the store but cannot guarantee
* registration order. Throws in the open-source package — requires
* `react-on-rails-pro`.
* @param name - The registered store name
* @returns Promise<Store>
*/
getOrWaitForStore(name);

/**
* **Pro only.** Get a store generator by name, or wait for it to be
* registered. Returns a Promise that resolves with the store generator
* function rather than a hydrated store instance. Throws in the
* open-source package — requires `react-on-rails-pro`.
* @param name - The registered store generator name
* @returns Promise<StoreGenerator>
*/
getOrWaitForStoreGenerator(name);

/**
* Renders or hydrates the React element passed. In case React version is >=18 will use the root API.
* @param domNode
* @param reactElement
* @param hydrate if true will perform hydration, if false will render
* @returns {Root|ReactComponent|ReactElement|null}
*/
reactHydrateOrRender(domNode, reactElement, hydrate);

/**
* Set options for ReactOnRails, typically before you call ReactOnRails.register
* Available Options:
* `traceTurbolinks: true|false` Gives you debugging messages on Turbolinks events
* `turbo: true|false` Register Turbo event listeners for page transitions.
* Set to true for apps using Hotwire Turbo (the Turbolinks successor).
* Default: false
* `debugMode: true|false` Enable debug mode for detailed logging of React on
* Rails operations (registration, rendering, Turbo lifecycle events).
* Default: false
* `logComponentRegistration: true|false` Log component registration details
* including timing and bundle size information to the browser console.
* Default: false
* `rootErrorHandlers: { onRecoverableError, onCaughtError, onUncaughtError }` React root error
* callbacks applied to every React root created by React on Rails. Each callback receives
* React's (error, errorInfo) plus a context object whose componentName and domNodeId fields
* are optional.
* Partial updates merge per key (setting one callback later keeps the others).
* onRecoverableError requires React 18+; onCaughtError/onUncaughtError require React 19.
* Unsupported React versions retain registrations for future upgrades, but the current runtime
* cannot invoke unsupported callbacks and logs a one-time warning.
* On React on Rails Pro RSC hydration roots, onRecoverableError is chained after Pro's
* internal default reporting instead of replacing it; do not report the same error again there.
* See https://reactonrails.com/docs/building-features/debugging-hydration-mismatches
*/
setOptions(options);

/**
* Allow directly calling the page loaded script in case the default events that trigger React
* rendering are not sufficient, such as when loading JavaScript asynchronously with TurboLinks:
* More details can be found here:
* https://reactonrails.com/docs/building-features/turbolinks
*/
reactOnRailsPageLoaded();

/**
* Triggers rendering for the component in the given DOM node and returns
* a Promise. In the open-source package, the Promise resolves immediately
* after initiating the render (it does not wait for deferred hydration
* modes like `hydrate_on: :visible` to complete). React on Rails Pro
* provides a richer implementation where the Promise reflects actual
* component load completion.
* @param domId - The DOM element ID of the React on Rails component mount
*/
reactOnRailsComponentLoaded(domId);

/**
* **Pro only.** Returns a Promise that resolves when the named Redux store
* has been registered and hydrated. Use when non-component code (analytics,
* router loaders, etc.) needs to wait for store availability. Throws in the
* open-source package — requires `react-on-rails-pro`.
* @param storeName - The registered store name
*/
reactOnRailsStoreLoaded(storeName);

/**
* Returns CSRF authenticity token inserted by Rails csrf_meta_tags
* @returns String or null
*/
authenticityToken();

/**
* Returns header with csrf authenticity token and XMLHttpRequest
* @param {*} other headers
* @returns {*} header
*/
authenticityHeaders((otherHeaders = {}));

For TanStack Router integration utilities, see react-on-rails-pro/tanstack-router (requires React on Rails Pro).