react-instantsearch-core 7.0.2 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/cjs/hooks/useConnector.js +1 -1
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/lib/InstantSearchRSCContext.js +9 -0
- package/dist/cjs/lib/use.js +15 -0
- package/dist/cjs/lib/useInstantSearchApi.js +18 -7
- package/dist/cjs/lib/useRSCContext.js +11 -0
- package/dist/cjs/lib/useSearchResults.js +1 -1
- package/dist/cjs/lib/useWidget.js +16 -1
- package/dist/cjs/lib/wrapPromiseWithState.js +32 -0
- package/dist/cjs/version.js +1 -1
- package/dist/es/hooks/useConnector.js +1 -1
- package/dist/es/index.d.ts +4 -0
- package/dist/es/index.js +4 -0
- package/dist/es/lib/InstantSearchRSCContext.d.ts +4 -0
- package/dist/es/lib/InstantSearchRSCContext.js +2 -0
- package/dist/es/lib/use.d.ts +3 -0
- package/dist/es/lib/use.js +5 -0
- package/dist/es/lib/useInstantSearchApi.js +18 -7
- package/dist/es/lib/useRSCContext.d.ts +1 -0
- package/dist/es/lib/useRSCContext.js +5 -0
- package/dist/es/lib/useSearchResults.js +1 -1
- package/dist/es/lib/useWidget.js +16 -1
- package/dist/es/lib/wrapPromiseWithState.d.ts +14 -0
- package/dist/es/lib/wrapPromiseWithState.js +26 -0
- package/dist/es/version.d.ts +1 -1
- package/dist/es/version.js +1 -1
- package/dist/umd/ReactInstantSearchCore.js +72 -15
- package/dist/umd/ReactInstantSearchCore.js.map +1 -1
- package/dist/umd/ReactInstantSearchCore.min.js +2 -2
- package/dist/umd/ReactInstantSearchCore.min.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
2
2
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
|
|
5
5
|
- [react-instantsearch-core](#react-instantsearch-core)
|
|
6
6
|
- [Installation](#installation)
|
|
@@ -19,7 +19,7 @@ React InstantSearch Core is an open-source UI library for React that lets you qu
|
|
|
19
19
|
InstantSearch’s goal is to help you implement awesome search experiences as smoothly as possible by providing a [complete search ecosystem](https://algolia.com/doc/guides/getting-started/how-algolia-works/#the-full-ecosystem). InstantSearch tackles an important part of this vast goal by providing front-end primitives that you can assemble into unique search interfaces.
|
|
20
20
|
|
|
21
21
|
<p align="center">
|
|
22
|
-
<a href="https://codesandbox.io/s/github/algolia/instantsearch
|
|
22
|
+
<a href="https://codesandbox.io/s/github/algolia/instantsearch/tree/master/examples/react/default-themes" title="Edit on CodeSandbox">
|
|
23
23
|
<img alt="Edit on CodeSandbox" src="https://codesandbox.io/static/img/play-codesandbox.svg">
|
|
24
24
|
</a>
|
|
25
25
|
</p>
|
|
@@ -65,7 +65,7 @@ To start contributing to code, you need to:
|
|
|
65
65
|
1. [Clone the repository](https://help.github.com/articles/cloning-a-repository/)
|
|
66
66
|
1. Install the dependencies: `yarn`
|
|
67
67
|
|
|
68
|
-
Please read [our contribution process](https://github.com/algolia/instantsearch
|
|
68
|
+
Please read [our contribution process](https://github.com/algolia/instantsearch/blob/master/CONTRIBUTING.md) to learn more.
|
|
69
69
|
|
|
70
70
|
## License
|
|
71
71
|
|
|
@@ -73,9 +73,9 @@ React InstantSearch is [MIT licensed](../../LICENSE).
|
|
|
73
73
|
|
|
74
74
|
<!-- Links -->
|
|
75
75
|
|
|
76
|
-
[contributing-bugreport]: https://github.com/algolia/instantsearch
|
|
77
|
-
[contributing-featurerequest]: https://github.com/algolia/instantsearch
|
|
78
|
-
[contributing-newissue]: https://github.com/algolia/instantsearch
|
|
79
|
-
[contributing-label-easy]: https://github.com/algolia/instantsearch
|
|
80
|
-
[contributing-label-bug]: https://github.com/algolia/instantsearch
|
|
81
|
-
[contributing-label-chore]: https://github.com/algolia/instantsearch
|
|
76
|
+
[contributing-bugreport]: https://github.com/algolia/instantsearch/issues/new?template=BUG_REPORT.yml&labels=triage,Library%3A%20React+InstantSearch
|
|
77
|
+
[contributing-featurerequest]: https://github.com/algolia/instantsearch/discussions/new?category=ideas&labels=triage,Library%3A%20React+InstantSearch&title=Feature%20request%3A%20
|
|
78
|
+
[contributing-newissue]: https://github.com/algolia/instantsearch/issues/new?labels=triage,Library%3A%20React+InstantSearch
|
|
79
|
+
[contributing-label-easy]: https://github.com/algolia/instantsearch/issues?q=is%3Aopen+is%3Aissue+label%3A%22Difficulty%3A+Easy%22+label%3A%22Library%3A%20React+InstantSearch%22
|
|
80
|
+
[contributing-label-bug]: https://github.com/algolia/instantsearch/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Bug%22+label%3A%22Library%3A%20React+InstantSearch%22
|
|
81
|
+
[contributing-label-chore]: https://github.com/algolia/instantsearch/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Chore%22+label%3A%22Library%3A%20React+InstantSearch%22
|
|
@@ -100,7 +100,7 @@ function useConnector(connector) {
|
|
|
100
100
|
|
|
101
101
|
// We get the widget render state by providing the same parameters as
|
|
102
102
|
// InstantSearch provides to the widget's `render` method.
|
|
103
|
-
// See https://github.com/algolia/instantsearch
|
|
103
|
+
// See https://github.com/algolia/instantsearch/blob/019cd18d0de6dd320284aa4890541b7fe2198c65/src/widgets/index/index.ts#L604-L617
|
|
104
104
|
var _widget$getWidgetRend = widget.getWidgetRenderState({
|
|
105
105
|
helper: helper,
|
|
106
106
|
parent: parentIndex,
|
package/dist/cjs/index.js
CHANGED
|
@@ -361,6 +361,54 @@ Object.keys(_useInstantSearch).forEach(function (key) {
|
|
|
361
361
|
}
|
|
362
362
|
});
|
|
363
363
|
});
|
|
364
|
+
var _wrapPromiseWithState = require("./lib/wrapPromiseWithState");
|
|
365
|
+
Object.keys(_wrapPromiseWithState).forEach(function (key) {
|
|
366
|
+
if (key === "default" || key === "__esModule") return;
|
|
367
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
368
|
+
if (key in exports && exports[key] === _wrapPromiseWithState[key]) return;
|
|
369
|
+
Object.defineProperty(exports, key, {
|
|
370
|
+
enumerable: true,
|
|
371
|
+
get: function get() {
|
|
372
|
+
return _wrapPromiseWithState[key];
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
var _useInstantSearchContext = require("./lib/useInstantSearchContext");
|
|
377
|
+
Object.keys(_useInstantSearchContext).forEach(function (key) {
|
|
378
|
+
if (key === "default" || key === "__esModule") return;
|
|
379
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
380
|
+
if (key in exports && exports[key] === _useInstantSearchContext[key]) return;
|
|
381
|
+
Object.defineProperty(exports, key, {
|
|
382
|
+
enumerable: true,
|
|
383
|
+
get: function get() {
|
|
384
|
+
return _useInstantSearchContext[key];
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
var _useRSCContext = require("./lib/useRSCContext");
|
|
389
|
+
Object.keys(_useRSCContext).forEach(function (key) {
|
|
390
|
+
if (key === "default" || key === "__esModule") return;
|
|
391
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
392
|
+
if (key in exports && exports[key] === _useRSCContext[key]) return;
|
|
393
|
+
Object.defineProperty(exports, key, {
|
|
394
|
+
enumerable: true,
|
|
395
|
+
get: function get() {
|
|
396
|
+
return _useRSCContext[key];
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
var _InstantSearchRSCContext = require("./lib/InstantSearchRSCContext");
|
|
401
|
+
Object.keys(_InstantSearchRSCContext).forEach(function (key) {
|
|
402
|
+
if (key === "default" || key === "__esModule") return;
|
|
403
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
404
|
+
if (key in exports && exports[key] === _InstantSearchRSCContext[key]) return;
|
|
405
|
+
Object.defineProperty(exports, key, {
|
|
406
|
+
enumerable: true,
|
|
407
|
+
get: function get() {
|
|
408
|
+
return _InstantSearchRSCContext[key];
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
});
|
|
364
412
|
var _server = require("./server");
|
|
365
413
|
Object.keys(_server).forEach(function (key) {
|
|
366
414
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.InstantSearchRSCContext = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var InstantSearchRSCContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
9
|
+
exports.InstantSearchRSCContext = InstantSearchRSCContext;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.use = void 0;
|
|
8
|
+
var React = _interopRequireWildcard(require("react"));
|
|
9
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
10
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
11
|
+
var useKey = 'use';
|
|
12
|
+
|
|
13
|
+
// @TODO: Remove this file and import directly from React when available.
|
|
14
|
+
var use = React[useKey];
|
|
15
|
+
exports.use = use;
|
|
@@ -7,10 +7,11 @@ exports.useInstantSearchApi = useInstantSearchApi;
|
|
|
7
7
|
var _InstantSearch = _interopRequireDefault(require("instantsearch.js/cjs/lib/InstantSearch"));
|
|
8
8
|
var _react = require("react");
|
|
9
9
|
var _shim = require("use-sync-external-store/shim");
|
|
10
|
-
var _useInstantSearchServerContext = require("../lib/useInstantSearchServerContext");
|
|
11
|
-
var _useInstantSearchSSRContext = require("../lib/useInstantSearchSSRContext");
|
|
12
10
|
var _version = _interopRequireDefault(require("../version"));
|
|
13
11
|
var _useForceUpdate = require("./useForceUpdate");
|
|
12
|
+
var _useInstantSearchServerContext = require("./useInstantSearchServerContext");
|
|
13
|
+
var _useInstantSearchSSRContext = require("./useInstantSearchSSRContext");
|
|
14
|
+
var _useRSCContext = require("./useRSCContext");
|
|
14
15
|
var _warn = require("./warn");
|
|
15
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
17
|
var defaultUserAgents = ["react (".concat(_react.version, ")"), "react-instantsearch (".concat(_version.default, ")"), "react-instantsearch-core (".concat(_version.default, ")")];
|
|
@@ -22,8 +23,10 @@ function useInstantSearchApi(props) {
|
|
|
22
23
|
var forceUpdate = (0, _useForceUpdate.useForceUpdate)();
|
|
23
24
|
var serverContext = (0, _useInstantSearchServerContext.useInstantSearchServerContext)();
|
|
24
25
|
var serverState = (0, _useInstantSearchSSRContext.useInstantSearchSSRContext)();
|
|
26
|
+
var waitingForResultsRef = (0, _useRSCContext.useRSCContext)();
|
|
25
27
|
var initialResults = serverState === null || serverState === void 0 ? void 0 : serverState.initialResults;
|
|
26
28
|
var prevPropsRef = (0, _react.useRef)(props);
|
|
29
|
+
var shouldRenderAtOnce = serverContext || initialResults || waitingForResultsRef;
|
|
27
30
|
var searchRef = (0, _react.useRef)(null);
|
|
28
31
|
// As we need to render on mount with SSR, using the local ref above in `StrictMode` will
|
|
29
32
|
// create and start two instances of InstantSearch. To avoid this, we instead discard it and use
|
|
@@ -34,7 +37,7 @@ function useInstantSearchApi(props) {
|
|
|
34
37
|
if (searchRef.current === null) {
|
|
35
38
|
// We don't use the `instantsearch()` function because it comes with other
|
|
36
39
|
// top-level APIs that we don't need.
|
|
37
|
-
// See https://github.com/algolia/instantsearch
|
|
40
|
+
// See https://github.com/algolia/instantsearch/blob/5b529f43d8acc680f85837eaaa41f7fd03a3f833/src/index.es.ts#L63-L86
|
|
38
41
|
var search = new _InstantSearch.default(props);
|
|
39
42
|
search._schedule = function _schedule(cb) {
|
|
40
43
|
search._schedule.queue.push(cb);
|
|
@@ -47,7 +50,7 @@ function useInstantSearchApi(props) {
|
|
|
47
50
|
}, 0);
|
|
48
51
|
};
|
|
49
52
|
search._schedule.queue = [];
|
|
50
|
-
if (
|
|
53
|
+
if (shouldRenderAtOnce) {
|
|
51
54
|
// InstantSearch.js has a private Initial Results API that lets us inject
|
|
52
55
|
// results on the search instance.
|
|
53
56
|
// On the server, we default the initial results to an empty object so that
|
|
@@ -61,7 +64,7 @@ function useInstantSearchApi(props) {
|
|
|
61
64
|
// On the server, we start the search early to compute the search parameters.
|
|
62
65
|
// On SSR, we start the search early to directly catch up with the lifecycle
|
|
63
66
|
// and render.
|
|
64
|
-
if (
|
|
67
|
+
if (shouldRenderAtOnce) {
|
|
65
68
|
search.start();
|
|
66
69
|
}
|
|
67
70
|
if (serverContext) {
|
|
@@ -72,6 +75,7 @@ function useInstantSearchApi(props) {
|
|
|
72
75
|
});
|
|
73
76
|
}
|
|
74
77
|
warnNextRouter(props.routing);
|
|
78
|
+
warnNextAppDir(Boolean(waitingForResultsRef));
|
|
75
79
|
searchRef.current = search;
|
|
76
80
|
}
|
|
77
81
|
{
|
|
@@ -179,6 +183,13 @@ function warnNextRouter(routing) {
|
|
|
179
183
|
process.env.NODE_ENV === 'development' ? (0, _warn.warn)(isUsingNextRouter, "\nYou are using Next.js with InstantSearch without the \"react-instantsearch-router-nextjs\" package.\nThis package is recommended to make the routing work correctly with Next.js.\nPlease check its usage instructions: https://github.com/algolia/instantsearch/tree/master/packages/react-instantsearch-router-nextjs\n\nYou can ignore this warning if you are using a custom router that suits your needs, it won't be outputted in production builds.") : void 0;
|
|
180
184
|
}
|
|
181
185
|
}
|
|
186
|
+
function warnNextAppDir(isRscContextDefined) {
|
|
187
|
+
var _next;
|
|
188
|
+
if (!(process.env.NODE_ENV === 'development') || typeof window === 'undefined' || isRscContextDefined) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
process.env.NODE_ENV === 'development' ? (0, _warn.warn)(Boolean((_next = window.next) === null || _next === void 0 ? void 0 : _next.appDir) === false, "\nWe've detected you are using Next.js with the App Router.\nWe released an **experimental** package called \"react-instantsearch-nextjs\" that makes SSR work with the App Router.\nPlease check its usage instructions: https://www.algolia.com/doc/guides/building-search-ui/going-further/server-side-rendering/react/#with-nextjs\n\nThis warning will not be outputted in production builds.") : void 0;
|
|
192
|
+
}
|
|
182
193
|
|
|
183
194
|
/**
|
|
184
195
|
* Gets the version of Next.js if it is available in the `window` object,
|
|
@@ -186,6 +197,6 @@ function warnNextRouter(routing) {
|
|
|
186
197
|
* which is either `nodejs` or `edge`.
|
|
187
198
|
*/
|
|
188
199
|
function getNextVersion() {
|
|
189
|
-
var
|
|
190
|
-
return typeof window !== 'undefined' && ((
|
|
200
|
+
var _next2, _process$env;
|
|
201
|
+
return typeof window !== 'undefined' && ((_next2 = window.next) === null || _next2 === void 0 ? void 0 : _next2.version) || (typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.NEXT_RUNTIME : undefined);
|
|
191
202
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useRSCContext = useRSCContext;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _InstantSearchRSCContext = require("./InstantSearchRSCContext");
|
|
9
|
+
function useRSCContext() {
|
|
10
|
+
return (0, _react.useContext)(_InstantSearchRSCContext.InstantSearchRSCContext);
|
|
11
|
+
}
|
|
@@ -29,7 +29,7 @@ function useSearchResults() {
|
|
|
29
29
|
|
|
30
30
|
// Results can be `null` when the first search is stalled.
|
|
31
31
|
// In this case, we skip the update.
|
|
32
|
-
// See: https://github.com/algolia/instantsearch
|
|
32
|
+
// See: https://github.com/algolia/instantsearch/blob/20996c7a159988c58e00ff24d2d2dc98af8b980f/src/widgets/index/index.ts#L652-L657
|
|
33
33
|
if (results !== null) {
|
|
34
34
|
setSearchResults({
|
|
35
35
|
results: results,
|
|
@@ -6,13 +6,17 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.useWidget = useWidget;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _dequal = require("./dequal");
|
|
9
|
+
var _use = require("./use");
|
|
9
10
|
var _useInstantSearchContext = require("./useInstantSearchContext");
|
|
10
11
|
var _useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect");
|
|
12
|
+
var _useRSCContext = require("./useRSCContext");
|
|
11
13
|
function useWidget(_ref) {
|
|
14
|
+
var _waitingForResultsRef;
|
|
12
15
|
var widget = _ref.widget,
|
|
13
16
|
parentIndex = _ref.parentIndex,
|
|
14
17
|
props = _ref.props,
|
|
15
18
|
shouldSsr = _ref.shouldSsr;
|
|
19
|
+
var waitingForResultsRef = (0, _useRSCContext.useRSCContext)();
|
|
16
20
|
var prevPropsRef = (0, _react.useRef)(props);
|
|
17
21
|
(0, _react.useEffect)(function () {
|
|
18
22
|
prevPropsRef.current = props;
|
|
@@ -72,7 +76,18 @@ function useWidget(_ref) {
|
|
|
72
76
|
});
|
|
73
77
|
};
|
|
74
78
|
}, [parentIndex, widget, shouldAddWidgetEarly, search, props]);
|
|
75
|
-
if (shouldAddWidgetEarly) {
|
|
79
|
+
if (shouldAddWidgetEarly || (waitingForResultsRef === null || waitingForResultsRef === void 0 ? void 0 : (_waitingForResultsRef = waitingForResultsRef.current) === null || _waitingForResultsRef === void 0 ? void 0 : _waitingForResultsRef.status) === 'pending') {
|
|
76
80
|
parentIndex.addWidgets([widget]);
|
|
77
81
|
}
|
|
82
|
+
if (typeof window === 'undefined' && waitingForResultsRef !== null && waitingForResultsRef !== void 0 && waitingForResultsRef.current &&
|
|
83
|
+
// We need the widgets contained in the index to be added before we trigger the search request.
|
|
84
|
+
widget.$$type !== 'ais.index') {
|
|
85
|
+
var _search$helper;
|
|
86
|
+
(0, _use.use)(waitingForResultsRef.current);
|
|
87
|
+
// If we made a second request because of DynamicWidgets, we need to wait for the second result,
|
|
88
|
+
// except for DynamicWidgets itself which needs to render its children after the first result.
|
|
89
|
+
if (widget.$$type !== 'ais.dynamicWidgets' && (_search$helper = search.helper) !== null && _search$helper !== void 0 && _search$helper.lastResults) {
|
|
90
|
+
(0, _use.use)(waitingForResultsRef.current);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
78
93
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.wrapPromiseWithState = wrapPromiseWithState;
|
|
7
|
+
// This is needed in order to work with RSC Suspense, perhaps they will later provide a wrapper.
|
|
8
|
+
|
|
9
|
+
function isStatefulPromise(promise) {
|
|
10
|
+
return 'status' in promise;
|
|
11
|
+
}
|
|
12
|
+
function wrapPromiseWithState(promise) {
|
|
13
|
+
if (isStatefulPromise(promise)) {
|
|
14
|
+
return promise;
|
|
15
|
+
}
|
|
16
|
+
var pendingPromise = promise;
|
|
17
|
+
pendingPromise.status = 'pending';
|
|
18
|
+
pendingPromise.then(function (value) {
|
|
19
|
+
if (pendingPromise.status === 'pending') {
|
|
20
|
+
var fulfilledPromise = pendingPromise;
|
|
21
|
+
fulfilledPromise.status = 'fulfilled';
|
|
22
|
+
fulfilledPromise.value = value;
|
|
23
|
+
}
|
|
24
|
+
}, function (reason) {
|
|
25
|
+
if (pendingPromise.status === 'pending') {
|
|
26
|
+
var rejectedPromise = pendingPromise;
|
|
27
|
+
rejectedPromise.status = 'rejected';
|
|
28
|
+
rejectedPromise.reason = reason;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return promise;
|
|
32
|
+
}
|
package/dist/cjs/version.js
CHANGED
|
@@ -94,7 +94,7 @@ export function useConnector(connector) {
|
|
|
94
94
|
|
|
95
95
|
// We get the widget render state by providing the same parameters as
|
|
96
96
|
// InstantSearch provides to the widget's `render` method.
|
|
97
|
-
// See https://github.com/algolia/instantsearch
|
|
97
|
+
// See https://github.com/algolia/instantsearch/blob/019cd18d0de6dd320284aa4890541b7fe2198c65/src/widgets/index/index.ts#L604-L617
|
|
98
98
|
var _widget$getWidgetRend = widget.getWidgetRenderState({
|
|
99
99
|
helper: helper,
|
|
100
100
|
parent: parentIndex,
|
package/dist/es/index.d.ts
CHANGED
|
@@ -28,4 +28,8 @@ export * from './connectors/useStats';
|
|
|
28
28
|
export * from './connectors/useToggleRefinement';
|
|
29
29
|
export * from './hooks/useConnector';
|
|
30
30
|
export * from './hooks/useInstantSearch';
|
|
31
|
+
export * from './lib/wrapPromiseWithState';
|
|
32
|
+
export * from './lib/useInstantSearchContext';
|
|
33
|
+
export * from './lib/useRSCContext';
|
|
34
|
+
export * from './lib/InstantSearchRSCContext';
|
|
31
35
|
export * from './server';
|
package/dist/es/index.js
CHANGED
|
@@ -28,4 +28,8 @@ export * from "./connectors/useStats.js";
|
|
|
28
28
|
export * from "./connectors/useToggleRefinement.js";
|
|
29
29
|
export * from "./hooks/useConnector.js";
|
|
30
30
|
export * from "./hooks/useInstantSearch.js";
|
|
31
|
+
export * from "./lib/wrapPromiseWithState.js";
|
|
32
|
+
export * from "./lib/useInstantSearchContext.js";
|
|
33
|
+
export * from "./lib/useRSCContext.js";
|
|
34
|
+
export * from "./lib/InstantSearchRSCContext.js";
|
|
31
35
|
export * from "./server/index.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PromiseWithState } from './wrapPromiseWithState';
|
|
2
|
+
import type { MutableRefObject } from 'react';
|
|
3
|
+
export type InstantSearchRSCContextApi = MutableRefObject<PromiseWithState<void> | null> | null;
|
|
4
|
+
export declare const InstantSearchRSCContext: import("react").Context<InstantSearchRSCContextApi>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import InstantSearch from "instantsearch.js/es/lib/InstantSearch.js";
|
|
2
2
|
import { useCallback, useRef, version as ReactVersion } from 'react';
|
|
3
3
|
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
|
|
4
|
-
import { useInstantSearchServerContext } from "./useInstantSearchServerContext.js";
|
|
5
|
-
import { useInstantSearchSSRContext } from "./useInstantSearchSSRContext.js";
|
|
6
4
|
import version from "../version.js";
|
|
7
5
|
import { useForceUpdate } from "./useForceUpdate.js";
|
|
6
|
+
import { useInstantSearchServerContext } from "./useInstantSearchServerContext.js";
|
|
7
|
+
import { useInstantSearchSSRContext } from "./useInstantSearchSSRContext.js";
|
|
8
|
+
import { useRSCContext } from "./useRSCContext.js";
|
|
8
9
|
import { warn } from "./warn.js";
|
|
9
10
|
var defaultUserAgents = ["react (".concat(ReactVersion, ")"), "react-instantsearch (".concat(version, ")"), "react-instantsearch-core (".concat(version, ")")];
|
|
10
11
|
var serverUserAgent = "react-instantsearch-server (".concat(version, ")");
|
|
@@ -15,8 +16,10 @@ export function useInstantSearchApi(props) {
|
|
|
15
16
|
var forceUpdate = useForceUpdate();
|
|
16
17
|
var serverContext = useInstantSearchServerContext();
|
|
17
18
|
var serverState = useInstantSearchSSRContext();
|
|
19
|
+
var waitingForResultsRef = useRSCContext();
|
|
18
20
|
var initialResults = serverState === null || serverState === void 0 ? void 0 : serverState.initialResults;
|
|
19
21
|
var prevPropsRef = useRef(props);
|
|
22
|
+
var shouldRenderAtOnce = serverContext || initialResults || waitingForResultsRef;
|
|
20
23
|
var searchRef = useRef(null);
|
|
21
24
|
// As we need to render on mount with SSR, using the local ref above in `StrictMode` will
|
|
22
25
|
// create and start two instances of InstantSearch. To avoid this, we instead discard it and use
|
|
@@ -27,7 +30,7 @@ export function useInstantSearchApi(props) {
|
|
|
27
30
|
if (searchRef.current === null) {
|
|
28
31
|
// We don't use the `instantsearch()` function because it comes with other
|
|
29
32
|
// top-level APIs that we don't need.
|
|
30
|
-
// See https://github.com/algolia/instantsearch
|
|
33
|
+
// See https://github.com/algolia/instantsearch/blob/5b529f43d8acc680f85837eaaa41f7fd03a3f833/src/index.es.ts#L63-L86
|
|
31
34
|
var search = new InstantSearch(props);
|
|
32
35
|
search._schedule = function _schedule(cb) {
|
|
33
36
|
search._schedule.queue.push(cb);
|
|
@@ -40,7 +43,7 @@ export function useInstantSearchApi(props) {
|
|
|
40
43
|
}, 0);
|
|
41
44
|
};
|
|
42
45
|
search._schedule.queue = [];
|
|
43
|
-
if (
|
|
46
|
+
if (shouldRenderAtOnce) {
|
|
44
47
|
// InstantSearch.js has a private Initial Results API that lets us inject
|
|
45
48
|
// results on the search instance.
|
|
46
49
|
// On the server, we default the initial results to an empty object so that
|
|
@@ -54,7 +57,7 @@ export function useInstantSearchApi(props) {
|
|
|
54
57
|
// On the server, we start the search early to compute the search parameters.
|
|
55
58
|
// On SSR, we start the search early to directly catch up with the lifecycle
|
|
56
59
|
// and render.
|
|
57
|
-
if (
|
|
60
|
+
if (shouldRenderAtOnce) {
|
|
58
61
|
search.start();
|
|
59
62
|
}
|
|
60
63
|
if (serverContext) {
|
|
@@ -65,6 +68,7 @@ export function useInstantSearchApi(props) {
|
|
|
65
68
|
});
|
|
66
69
|
}
|
|
67
70
|
warnNextRouter(props.routing);
|
|
71
|
+
warnNextAppDir(Boolean(waitingForResultsRef));
|
|
68
72
|
searchRef.current = search;
|
|
69
73
|
}
|
|
70
74
|
{
|
|
@@ -172,6 +176,13 @@ function warnNextRouter(routing) {
|
|
|
172
176
|
process.env.NODE_ENV === 'development' ? warn(isUsingNextRouter, "\nYou are using Next.js with InstantSearch without the \"react-instantsearch-router-nextjs\" package.\nThis package is recommended to make the routing work correctly with Next.js.\nPlease check its usage instructions: https://github.com/algolia/instantsearch/tree/master/packages/react-instantsearch-router-nextjs\n\nYou can ignore this warning if you are using a custom router that suits your needs, it won't be outputted in production builds.") : void 0;
|
|
173
177
|
}
|
|
174
178
|
}
|
|
179
|
+
function warnNextAppDir(isRscContextDefined) {
|
|
180
|
+
var _next;
|
|
181
|
+
if (!(process.env.NODE_ENV === 'development') || typeof window === 'undefined' || isRscContextDefined) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
process.env.NODE_ENV === 'development' ? warn(Boolean((_next = window.next) === null || _next === void 0 ? void 0 : _next.appDir) === false, "\nWe've detected you are using Next.js with the App Router.\nWe released an **experimental** package called \"react-instantsearch-nextjs\" that makes SSR work with the App Router.\nPlease check its usage instructions: https://www.algolia.com/doc/guides/building-search-ui/going-further/server-side-rendering/react/#with-nextjs\n\nThis warning will not be outputted in production builds.") : void 0;
|
|
185
|
+
}
|
|
175
186
|
|
|
176
187
|
/**
|
|
177
188
|
* Gets the version of Next.js if it is available in the `window` object,
|
|
@@ -179,6 +190,6 @@ function warnNextRouter(routing) {
|
|
|
179
190
|
* which is either `nodejs` or `edge`.
|
|
180
191
|
*/
|
|
181
192
|
function getNextVersion() {
|
|
182
|
-
var
|
|
183
|
-
return typeof window !== 'undefined' && ((
|
|
193
|
+
var _next2, _process$env;
|
|
194
|
+
return typeof window !== 'undefined' && ((_next2 = window.next) === null || _next2 === void 0 ? void 0 : _next2.version) || (typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.NEXT_RUNTIME : undefined);
|
|
184
195
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useRSCContext(): import("./InstantSearchRSCContext").InstantSearchRSCContextApi;
|
|
@@ -23,7 +23,7 @@ export function useSearchResults() {
|
|
|
23
23
|
|
|
24
24
|
// Results can be `null` when the first search is stalled.
|
|
25
25
|
// In this case, we skip the update.
|
|
26
|
-
// See: https://github.com/algolia/instantsearch
|
|
26
|
+
// See: https://github.com/algolia/instantsearch/blob/20996c7a159988c58e00ff24d2d2dc98af8b980f/src/widgets/index/index.ts#L652-L657
|
|
27
27
|
if (results !== null) {
|
|
28
28
|
setSearchResults({
|
|
29
29
|
results: results,
|
package/dist/es/lib/useWidget.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { useEffect, useRef } from 'react';
|
|
2
2
|
import { dequal } from "./dequal.js";
|
|
3
|
+
import { use } from "./use.js";
|
|
3
4
|
import { useInstantSearchContext } from "./useInstantSearchContext.js";
|
|
4
5
|
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
6
|
+
import { useRSCContext } from "./useRSCContext.js";
|
|
5
7
|
export function useWidget(_ref) {
|
|
8
|
+
var _waitingForResultsRef;
|
|
6
9
|
var widget = _ref.widget,
|
|
7
10
|
parentIndex = _ref.parentIndex,
|
|
8
11
|
props = _ref.props,
|
|
9
12
|
shouldSsr = _ref.shouldSsr;
|
|
13
|
+
var waitingForResultsRef = useRSCContext();
|
|
10
14
|
var prevPropsRef = useRef(props);
|
|
11
15
|
useEffect(function () {
|
|
12
16
|
prevPropsRef.current = props;
|
|
@@ -66,7 +70,18 @@ export function useWidget(_ref) {
|
|
|
66
70
|
});
|
|
67
71
|
};
|
|
68
72
|
}, [parentIndex, widget, shouldAddWidgetEarly, search, props]);
|
|
69
|
-
if (shouldAddWidgetEarly) {
|
|
73
|
+
if (shouldAddWidgetEarly || (waitingForResultsRef === null || waitingForResultsRef === void 0 ? void 0 : (_waitingForResultsRef = waitingForResultsRef.current) === null || _waitingForResultsRef === void 0 ? void 0 : _waitingForResultsRef.status) === 'pending') {
|
|
70
74
|
parentIndex.addWidgets([widget]);
|
|
71
75
|
}
|
|
76
|
+
if (typeof window === 'undefined' && waitingForResultsRef !== null && waitingForResultsRef !== void 0 && waitingForResultsRef.current &&
|
|
77
|
+
// We need the widgets contained in the index to be added before we trigger the search request.
|
|
78
|
+
widget.$$type !== 'ais.index') {
|
|
79
|
+
var _search$helper;
|
|
80
|
+
use(waitingForResultsRef.current);
|
|
81
|
+
// If we made a second request because of DynamicWidgets, we need to wait for the second result,
|
|
82
|
+
// except for DynamicWidgets itself which needs to render its children after the first result.
|
|
83
|
+
if (widget.$$type !== 'ais.dynamicWidgets' && (_search$helper = search.helper) !== null && _search$helper !== void 0 && _search$helper.lastResults) {
|
|
84
|
+
use(waitingForResultsRef.current);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
72
87
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface PendingPromise<TValue> extends Promise<TValue> {
|
|
2
|
+
status: 'pending';
|
|
3
|
+
}
|
|
4
|
+
interface FulfilledPromise<TValue> extends Promise<TValue> {
|
|
5
|
+
status: 'fulfilled';
|
|
6
|
+
value: TValue;
|
|
7
|
+
}
|
|
8
|
+
interface RejectedPromise<TValue> extends Promise<TValue> {
|
|
9
|
+
status: 'rejected';
|
|
10
|
+
reason: unknown;
|
|
11
|
+
}
|
|
12
|
+
export type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;
|
|
13
|
+
export declare function wrapPromiseWithState<TValue>(promise: Promise<TValue>): PromiseWithState<TValue>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// This is needed in order to work with RSC Suspense, perhaps they will later provide a wrapper.
|
|
2
|
+
|
|
3
|
+
function isStatefulPromise(promise) {
|
|
4
|
+
return 'status' in promise;
|
|
5
|
+
}
|
|
6
|
+
export function wrapPromiseWithState(promise) {
|
|
7
|
+
if (isStatefulPromise(promise)) {
|
|
8
|
+
return promise;
|
|
9
|
+
}
|
|
10
|
+
var pendingPromise = promise;
|
|
11
|
+
pendingPromise.status = 'pending';
|
|
12
|
+
pendingPromise.then(function (value) {
|
|
13
|
+
if (pendingPromise.status === 'pending') {
|
|
14
|
+
var fulfilledPromise = pendingPromise;
|
|
15
|
+
fulfilledPromise.status = 'fulfilled';
|
|
16
|
+
fulfilledPromise.value = value;
|
|
17
|
+
}
|
|
18
|
+
}, function (reason) {
|
|
19
|
+
if (pendingPromise.status === 'pending') {
|
|
20
|
+
var rejectedPromise = pendingPromise;
|
|
21
|
+
rejectedPromise.status = 'rejected';
|
|
22
|
+
rejectedPromise.reason = reason;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return promise;
|
|
26
|
+
}
|
package/dist/es/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "7.0
|
|
1
|
+
declare const _default: "7.1.0";
|
|
2
2
|
export default _default;
|
package/dist/es/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '7.0
|
|
1
|
+
export default '7.1.0';
|