Skip to content

Commit 5f939b4

Browse files
committed
Docs: frame Redux as legacy shared-store guidance
1 parent c7b54be commit 5f939b4

12 files changed

Lines changed: 99 additions & 63 deletions

docs/oss/api-reference/generator-details.md

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Generator Details
22

3-
The `react_on_rails:install` generator combined with the example pull requests of generator runs will get you up and running efficiently. There's a fair bit of setup with integrating a bundler with Rails. Most options default to off — for example, the default for `-R` is that `redux` is off. The exception is the bundler: **fresh installs now default to Rspack**, so pass `--no-rspack` (or its alias `--webpack`) if you want Webpack instead. Existing apps that already declare a bundler in `config/shakapacker.yml` are left unchanged.
3+
The `react_on_rails:install` generator combined with the example pull requests of generator runs will get you up and running efficiently. There's a fair bit of setup with integrating a bundler with Rails. Most options default to off. The exception is the bundler: **fresh installs now default to Rspack**, so pass `--no-rspack` (or its alias `--webpack`) if you want Webpack instead. Existing apps that already declare a bundler in `config/shakapacker.yml` are left unchanged.
44

55
Run `rails generate react_on_rails:install --help` for descriptions of all available options:
66

@@ -9,7 +9,6 @@ Usage:
99
rails generate react_on_rails:install [options]
1010
1111
Options:
12-
-R, [--redux], [--no-redux] # Install Redux package and Redux version of Hello World Example. Default: false
1312
-T, [--typescript], [--no-typescript] # Generate TypeScript files and install TypeScript dependencies. Default: false
1413
[--rspack], [--no-rspack] # Use Rspack (default) as the bundler; pass --no-rspack to use Webpack
1514
[--webpack], [--no-webpack] # Use Webpack as the bundler (alias for --no-rspack)
@@ -27,13 +26,17 @@ Runtime options:
2726
Description:
2827
2928
The react_on_rails:install generator integrates webpack with rails with ease. You
30-
can pass the redux option if you'd like to have redux setup for you automatically.
31-
32-
* Redux
33-
34-
Passing the --redux generator option causes the generated Hello World example
35-
to integrate the Redux state container framework. The necessary node modules
36-
will be automatically included for you.
29+
can pass the options below to customize the generated example and supporting
30+
configuration.
31+
32+
> [!WARNING]
33+
> The Redux installer path (`--redux` / `-R`) is a hidden legacy escape hatch, not
34+
> a recommended starter architecture. New apps should start with plain
35+
> `react_component` entries, React local state or context for island-local UI
36+
> state, and Rails props or server-state tools such as TanStack Query for data
37+
> loaded from the server. Use Redux only for an existing Redux app or an advanced
38+
> multi-island page where separate React roots must coordinate through one shared
39+
> client store.
3740
3841
* TypeScript
3942
@@ -82,9 +85,9 @@ Another good option is to create a simple test app per the [Tutorial](../getting
8285

8386
## Understanding the Organization of the Generated Client Code
8487

85-
The React on Rails generator creates different directory structures depending on whether you use the `--redux` option.
88+
The React on Rails generator normally creates the simple component structure below. A hidden legacy Redux path remains available for existing apps and recovery work, but it is not the structure recommended for new React on Rails apps.
8689

87-
### Default Structure (Without Redux)
90+
### Default Structure (Recommended, Without Redux)
8891

8992
The basic generator creates a simple, flat structure optimized for auto-bundling:
9093

@@ -104,9 +107,9 @@ app/javascript/
104107

105108
For components that need different client vs. server implementations, use `.client.jsx` and `.server.jsx` suffixes (e.g., `HelloWorld.client.jsx` and `HelloWorld.server.jsx`).
106109

107-
### Redux Structure (With `--redux` Option)
110+
### Legacy Redux Structure (Hidden `--redux` Path)
108111

109-
The Redux generator creates a more structured organization with familiar Redux patterns:
112+
The hidden legacy Redux generator creates a more structured organization with familiar Redux patterns:
110113

111114
```text
112115
app/javascript/
@@ -130,13 +133,21 @@ app/javascript/
130133
└── helloWorldStore.js
131134
```
132135

133-
This structure follows Redux best practices:
136+
This legacy structure is useful only when you intentionally maintain Redux:
134137

135138
- **`components/`**: Presentational "dumb" components that receive data via props
136139
- **`containers/`**: Container "smart" components connected to Redux store
137140
- **`actions/`** and **`reducers/`**: Standard Redux patterns
138141
- **`ror_components/`**: Entry point files that initialize Redux and render the app
139142

143+
If you already have a React on Rails app and intentionally need to recreate the legacy Redux example, use the direct hidden generator after the base installer has configured React on Rails:
144+
145+
```bash
146+
rails generate react_on_rails:react_with_redux --typescript
147+
```
148+
149+
For full install recovery of an older Redux-generated app, the hidden `react_on_rails:install --redux` option still exists, but do not use it for greenfield apps.
150+
140151
### TypeScript Support
141152

142153
The generator also supports a `--typescript` option for generating TypeScript files:
@@ -206,11 +217,8 @@ For apps with custom webpack configurations, review the generated config templat
206217
# Rspack (default) with TypeScript
207218
rails generate react_on_rails:install --typescript
208219

209-
# Webpack with Redux
210-
rails generate react_on_rails:install --no-rspack --redux
211-
212-
# Explicit Rspack with TypeScript and Redux
213-
rails generate react_on_rails:install --rspack --typescript --redux
220+
# Webpack with TypeScript
221+
rails generate react_on_rails:install --no-rspack --typescript
214222
```
215223

216224
For more details on Rspack configuration, see the [Webpack Configuration](../core-concepts/webpack-configuration.md#rspack-vs-webpack) docs.
@@ -246,9 +254,6 @@ For production, configure your license token: `export REACT_ON_RAILS_PRO_LICENSE
246254
# Pro with TypeScript
247255
rails generate react_on_rails:install --pro --typescript
248256

249-
# Pro with Redux
250-
rails generate react_on_rails:install --pro --redux
251-
252257
# Pro with Rspack
253258
rails generate react_on_rails:install --pro --rspack
254259
```
@@ -300,13 +305,12 @@ In addition to all Pro files:
300305
# RSC with TypeScript
301306
rails generate react_on_rails:install --rsc --typescript
302307

303-
# RSC with Redux (generates both HelloWorldApp and HelloServer)
304-
rails generate react_on_rails:install --rsc --redux
305-
306308
# RSC with Rspack
307309
rails generate react_on_rails:install --rsc --rspack
308310
```
309311

312+
Do not combine RSC with the hidden legacy Redux installer for new apps. Existing Redux Client Components can continue to work beside RSC when Redux access stays in Client Components; see [RSC context and state migration](../migrating/rsc-context-and-state.md#redux-toolkit).
313+
310314
**Upgrading an existing Pro app to RSC:**
311315

312316
For existing Pro apps, use the standalone RSC generator:

docs/oss/api-reference/javascript-api.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ The best source of docs is the `interface ReactOnRails` in [types/index.ts](http
4848
register(components);
4949

5050
/**
51-
* Allows registration of store generators to be used by multiple React components on one Rails
52-
* view. Store generators are functions that take one arg, props, and return a store. Note that
53-
* the setStore API is different in that it's the actual store hydrated with props.
51+
* Allows registration of store generators for legacy or advanced pages where multiple React
52+
* roots on one Rails view share a Redux store. Store generators receive props and railsContext,
53+
* then return a store. Note that the setStore API is different in that it's the actual store
54+
* hydrated with props.
5455
* @param stores (key is store name, value is the store generator)
5556
*/
5657
registerStoreGenerators(storesGenerators);

docs/oss/api-reference/redux-store-api.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
1-
# Redux Store
1+
# Redux Store API
22

33
> [!WARNING]
44
>
5-
> This Redux API is no longer recommended as it prevents dynamic code splitting for performance. Instead, you should use the standard `react_component` view helper passing in a "Render-Function."
5+
> This runtime API remains supported for existing apps and advanced shared-store use cases, but it is not recommended as the default state model for new React on Rails apps. Prefer the standard `react_component` view helper with props or a render-function unless multiple React islands must coordinate through one client store.
66
77
> [!IMPORTANT]
88
>
99
> **Script Loading Requirement:** If you use Redux shared stores with inline component registration (registering components in view templates with `<script>ReactOnRails.register({ MyComponent })</script>`), you **must use `defer: true`** in your `javascript_pack_tag` instead of `async: true`. With async loading, the bundle may execute before inline scripts, causing component registration failures. See the [Streaming Server Rendering documentation](../building-features/streaming-server-rendering.md#important-redux-shared-store-caveat) for details and alternatives.
1010
11-
You don't need to use the `redux_store` api to use Redux. This API was set up to support multiple calls to `react_component` on one page that all talk to the same Redux store.
11+
You don't need to use the `redux_store` API to use Redux inside a single React root. This API was set up to support multiple calls to `react_component` on one page that all talk to the same Redux store.
1212

13-
If you are only rendering one React component on a page, as is typical to do a "Single Page App" in React, then you should _probably_ pass the props to your React component in a "Render-Function."
13+
If you are rendering one React component on a page, pass props to that component through `react_component` and keep local UI state inside that React tree. A render-function is also a better fit when you need `railsContext`, routing setup, or custom hydration behavior for one root.
1414

15-
Consider using the `redux_store` helper for the two following use cases:
15+
Choose state ownership before reaching for `redux_store`:
16+
17+
- **Local island state:** use React Hooks or React Context inside one `react_component` root.
18+
- **Server state:** use Rails controller props for initial data, then Rails JSON endpoints, GraphQL, or a server-state cache such as [TanStack Query](../building-features/tanstack-query.md) for data that belongs on the server.
19+
- **Multi-island shared client state:** use `redux_store` when separate React roots on one Rails page must read and update the same client-side state.
20+
21+
Consider using the `redux_store` helper for the following advanced use cases:
1622

1723
1. You want to have multiple React components accessing the same store at once.
1824
2. You want to place the props to hydrate the client side stores at the very end of your HTML, probably server rendered, so that the browser can render all earlier HTML first. This is particularly useful if your props will be large. However, you're probably better off using [React on Rails Pro](../../pro/react-on-rails-pro.md) if you're at all concerned about performance.
1925

20-
## Multiple React Components on a Page with One Store
26+
## Multiple React Islands on a Page with One Store
2127

22-
You may wish to have 2 React components share the same the Redux store. For example, if your navbar is a React component, you may want it to use the same store as your component in the main area of the page. You may even want multiple React components in the main area, which allows for greater modularity. Also, you may want this to work with Turbolinks to minimize reloading the JavaScript.
28+
You may wish to have two separate React roots share the same Redux store. For example, if your navbar is a React component, you may want it to use the same store as your component in the main area of the page. You may even want multiple React components in the main area, which allows for greater modularity. Also, you may want this to work with Turbo or Turbolinks to minimize reloading the JavaScript.
2329

2430
A good example of this would be something like a notifications counter in a header. As each notification is read in the body of the page, you would like to update the header. If both the header and body share the same Redux store, then this is trivial. Otherwise, we have to rely on other solutions, such as the header polling the server to see how many unread notifications exist.
2531

docs/oss/building-features/react-and-redux.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
# Communication between React Components and Redux Reducers
1+
# Legacy Redux Reducer Guidance
2+
3+
Redux remains supported for existing React on Rails apps and advanced pages that need one client store shared across multiple React roots. For new apps, prefer local component state for island-specific UI, Rails props plus server-state tools for server-owned data, and reach for Redux only when those smaller patterns do not fit.
24

35
## Communication Between Components
46

57
See [Sharing State Between Components](https://react.dev/learn/sharing-state-between-components).
68

79
## Redux Reducers
810

9-
The `helloWorld/reducers/index.jsx` example that results from running the generator with the Redux option may be slightly confusing because of its simplicity. For clarity, what follows is a more fleshed-out example of what a reducer might look like:
11+
The `helloWorld/reducers/index.jsx` example from the hidden legacy Redux generator may be slightly confusing because of its simplicity. For clarity, what follows is a more fleshed-out example of what a reducer might look like:
1012

1113
```javascript
1214
import usersReducer from './usersReducer';

docs/oss/building-features/react-router.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,34 @@ React Router v6 offers multiple routing approaches. For React on Rails, we recom
3737

3838
**Note on Data Mode:** React Router's Data Mode (with loaders/actions) is designed for SPAs where the client handles data fetching. Since React on Rails uses Rails controllers to load data and pass it as props to React components, Data Mode would create duplicate data loading. Stick with Declarative Mode to leverage React on Rails' server-side data loading pattern.
3939

40-
## Basic Client-Side Setup with Redux
40+
## Basic Client-Side Setup
4141

42-
If you're using Redux (created with `rails generate react_on_rails:install --redux`), you can add React Router by wrapping your app:
42+
Most React Router integrations do not need Redux. Route ordinary components inside one React root, pass initial data from Rails as props, and use your normal server-state approach for follow-up data loading.
43+
44+
**File: `app/javascript/src/RouterApp/ror_components/RouterApp.client.jsx`**
45+
46+
```jsx
47+
import React from 'react';
48+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
49+
50+
const Home = ({ name }) => <div>Hello, {name}!</div>;
51+
const About = () => <div>About</div>;
52+
53+
const RouterApp = (props) => (
54+
<BrowserRouter>
55+
<Routes>
56+
<Route path="/" element={<Home {...props} />} />
57+
<Route path="/about" element={<About />} />
58+
</Routes>
59+
</BrowserRouter>
60+
);
61+
62+
export default RouterApp;
63+
```
64+
65+
## Legacy Client-Side Setup with Redux
66+
67+
If you're maintaining an app that already uses Redux, including the hidden legacy Redux generator output, you can add React Router by wrapping your app:
4368

4469
**File: `app/javascript/src/HelloWorldApp/ror_components/HelloWorldApp.client.jsx`**
4570

@@ -76,7 +101,7 @@ export default HelloWorldApp;
76101

77102
**Key points:**
78103

79-
- `<Provider>` wraps `<BrowserRouter>` so all routes have Redux access
104+
- In Redux-backed legacy apps, `<Provider>` wraps `<BrowserRouter>` so all routes have Redux access
80105
- Use `<Routes>` and `<Route>` (not `<Switch>` from React Router v5)
81106
- Use `element` prop to specify components (not `component` or `render` props from v5)
82107
- Routes are automatically matched by best fit, not render order

docs/oss/core-concepts/auto-bundling-file-system-based-automated-bundle-generation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ As of version 13.3.4, bundles inside directories that match `config.components_s
728728
## Redux Store Auto-Registration
729729

730730
> [!NOTE]
731-
> Most applications use React components without Redux. If you don't use Redux stores, you can skip this section entirely.
731+
> Most applications use React components without Redux. If you don't maintain a legacy Redux app or an advanced multi-island shared store, you can skip this section entirely.
732732

733733
In addition to components, React on Rails can automatically register Redux stores based on file system conventions. This eliminates manual `ReactOnRails.registerStore()` calls and generates individual packs for each store. The feature works the same way as component auto-registration.
734734

docs/oss/core-concepts/how-react-on-rails-works.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Ensure these generated bundle files are in your `.gitignore`, as you never want
88

99
Inside your Rails views, you can now use the `react_component` helper method provided by React on Rails. You can pass props directly to the React component helper.
1010

11-
Optionally, you can also initialize a Redux store with the view or controller helper `redux_store` so that the Redux store can be shared amongst multiple React components.
11+
For legacy or advanced shared-store pages, you can also initialize a Redux store with the view or controller helper `redux_store` so that separate React roots can coordinate through one client store.
1212

1313
## Client-Side Rendering vs. Server-Side Rendering
1414

docs/oss/core-concepts/render-functions-and-railscontext.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Render-Functions
44

55
When you use a render-function to create React components (or `renderedHtml` on the server), or you
6-
use shared Redux stores, you get two params passed to your function that creates a React component:
6+
register legacy or advanced shared Redux stores, React on Rails passes two params to the function it calls:
77

88
1. `props`: Props that you pass in the view helper of either `react_component` or `redux_store`
99
2. `railsContext`: Rails contextual information, such as the current pathname. You can customize
@@ -78,7 +78,7 @@ reduxStore = MyReduxStore(props, railsContext);
7878
> You never make these calls. React on Rails makes these calls when it does either client or server rendering. You will define functions that take these 2 params and return a React component or a Redux Store. Naturally, you do not have to use second parameter, `railsContext`, if you do not need it. If you don't take a second parameter, then you're probably defining a React function component and you will simply return a React Element, often just JSX.
7979
8080
> [!NOTE]
81-
> See [Redux Store](../api-reference/redux-store-api.md#multiple-react-components-on-a-page-with-one-store) on how to set up Redux stores that allow multiple components to talk to the same store.
81+
> See [Redux Store](../api-reference/redux-store-api.md#multiple-react-islands-on-a-page-with-one-store) on how to set up Redux stores that allow multiple React roots to talk to the same store.
8282
8383
The `railsContext` has: (see the implementation in [ReactOnRails::Helper](https://github.com/shakacode/react_on_rails/blob/main/react_on_rails/lib/react_on_rails/helper.rb), method `rails_context` for the definitive list).
8484

docs/oss/getting-started/quick-start.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ Now that you have React on Rails working, here's what to explore next:
190190

191191
### Advanced Features
192192

193-
1. **[Redux Integration](../building-features/react-and-redux.md)** - Manage application state
193+
1. **[Redux Integration](../building-features/react-and-redux.md)** - Maintain legacy or advanced shared-store integrations
194194
2. **[React Router](../building-features/react-router.md)** - Client-side routing
195195

196196
### Pro Features

0 commit comments

Comments
 (0)