UNPKG

react-instantsearch-core

Version:
91 lines (90 loc) 3.45 kB
import { getInitialResults, waitForResults } from "instantsearch.js/es/lib/server.js"; import { walkIndex, resetWidgetId } from "instantsearch.js/es/lib/utils/index.js"; import React from 'react'; import { InstantSearchServerContext } from "../components/InstantSearchServerContext.js"; import { InstantSearchSSRProvider } from "../components/InstantSearchSSRProvider.js"; /** * Returns the InstantSearch server state from a component. */ export function getServerState(children, _ref) { var renderToString = _ref.renderToString; var searchRef = { current: undefined }; resetWidgetId(); var createNotifyServer = function createNotifyServer() { var hasBeenNotified = false; var notifyServer = function notifyServer(_ref2) { var search = _ref2.search; if (hasBeenNotified) { throw new Error('getServerState should be called with a single InstantSearchSSRProvider and a single InstantSearch component.'); } hasBeenNotified = true; searchRef.current = search; }; return notifyServer; }; return execute({ children: children, renderToString: renderToString, searchRef: searchRef, notifyServer: createNotifyServer() }).then(function (serverState) { var shouldRefetch = false; // <DynamicWidgets> requires another query to retrieve the dynamic widgets // to render. walkIndex(searchRef.current.mainIndex, function (index) { shouldRefetch = shouldRefetch || index.getWidgets().some(function (widget) { return widget.$$type === 'ais.dynamicWidgets'; }); }); if (shouldRefetch) { resetWidgetId(); return execute({ children: /*#__PURE__*/React.createElement(InstantSearchSSRProvider, serverState, children), renderToString: renderToString, searchRef: searchRef, notifyServer: createNotifyServer(), skipRecommend: true }); } return serverState; }); } function execute(_ref3) { var children = _ref3.children, renderToString = _ref3.renderToString, notifyServer = _ref3.notifyServer, searchRef = _ref3.searchRef, skipRecommend = _ref3.skipRecommend; return Promise.resolve().then(function () { renderToString(/*#__PURE__*/React.createElement(InstantSearchServerContext.Provider, { value: { notifyServer: notifyServer } }, children)); }).then(function () { return ( // We wait for the component to mount so that `notifyServer()` is called. new Promise(function (resolve) { return setTimeout(resolve, 0); }) ); }).then(function () { // If `notifyServer()` is not called by then, it means that <InstantSearch> // wasn't within the `children`. // We decide to go with a strict behavior in that case; throwing. If users have // some routes that don't mount the <InstantSearch> component, they would need // to try/catch the `getServerState()` call. // If this behavior turns out to be too strict for many users, we can decide // to warn instead of throwing. if (!searchRef.current) { throw new Error("Unable to retrieve InstantSearch's server state in `getServerState()`. Did you mount the <InstantSearch> component?"); } return waitForResults(searchRef.current, skipRecommend); }).then(function (requestParamsList) { return { initialResults: getInitialResults(searchRef.current.mainIndex, requestParamsList) }; }); }