Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#### New Features
- Camelizes keys with primitive values, in addition to hashes #946
- Expose alternative implementations for `ReactUJS.getConstructor` #1050
- Add support for multiple `require.context` with addition of `useContexts` #1221
- Update dependencies
- react to 17.0.2 #1218
- webpack to 5.74.0
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,22 @@ ReactRailsUJS.useContext(myCustomContext)

If `require` fails to find your component, [`ReactRailsUJS`](#ujs) falls back to the global namespace, described in [Use with Asset Pipeline](#use-with-asset-pipeline).

In some cases, having multiple `require.context` entries may be desired. In a larger application, you might find it helpful to split your JavaScript by routes/controllers to avoid serving unused components and improve your site performance by keeping bundles smaller. For example, you might have separate bundles for homepage, search, and checkout routes. In that scenario, you can add an array of `require.context` component directory paths via `useContexts` to `server_rendering.js`, to allow for [Server-Side Rendering](#server-side-rendering) across your application

```js
// server_rendering.js
var homepageRequireContext = require.context('homepage', true);
var searchRequireContext = require.context('search', true);
var checkoutRequireContext = require.context('checkout', true);

var ReactRailsUJS = require('react_ujs');
ReactRailsUJS.useContexts([
homepageRequireContext,
searchRequireContext,
checkoutRequireContext
]);
```

### File naming

React-Rails supports plenty of file extensions such as: .js, .jsx.js, .js.jsx, .es6.js, .coffee, etcetera!
Expand Down
8 changes: 8 additions & 0 deletions react_ujs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var detectEvents = require("./src/events/detect")
var constructorFromGlobal = require("./src/getConstructor/fromGlobal")
var constructorFromRequireContext = require("./src/getConstructor/fromRequireContext")
var constructorFromRequireContextWithGlobalFallback = require("./src/getConstructor/fromRequireContextWithGlobalFallback")
var constructorFromRequireContextsWithGlobalFallback = require("./src/getConstructor/fromRequireContextsWithGlobalFallback")
const { supportsHydration, reactHydrate, createReactRootLike } = require("./src/renderHelpers")

var ReactRailsUJS = {
Expand Down Expand Up @@ -79,6 +80,13 @@ var ReactRailsUJS = {
this.getConstructor = constructorFromRequireContextWithGlobalFallback(requireContext)
},

// Given an array of Webpack `require.context`,
// try finding components with `require`,
// then falling back to global lookup.
useContexts: function(requireContexts) {
this.getConstructor = constructorFromRequireContextsWithGlobalFallback(requireContexts)
},

// Render `componentName` with `props` to a string,
// using the specified `renderFunction` from `react-dom/server`.
serverRender: function(renderFunction, componentName, props) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Make a function which:
// - First tries to require the name
// - Then falls back to global lookup
var fromGlobal = require("./fromGlobal");
var fromRequireContext = require("./fromRequireContext");

module.exports = function (reqctxs) {
var fromCtxs = reqctxs.map((reqctx) => fromRequireContext(reqctx));
return function (className) {
var component;
try {
var index = 0,
fromCtx,
firstErr;
do {
fromCtx = fromCtxs[index];

try {
// `require` will raise an error if this className isn't found:
component = fromCtx(className);
} catch (fromCtxErr) {
if (!firstErr) {
firstErr = fromCtxErr;
}
}

index += 1;
} while (index < fromCtxs.length);
if (!component) throw firstErr;
} catch (firstErr) {
// fallback to global:
try {
component = fromGlobal(className);
} catch (secondErr) {
console.error(firstErr);
console.error(secondErr);
}
}
return component;
};
};