Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

Commit

Permalink
fix(ssr): make sure metadata is available on initial render (#2973)
Browse files Browse the repository at this point in the history
## Summary

Metadata isn't available on initial render/ server rendered page. This is because registerWidget is added only in componentDidMount, as well as only registering its change to instantsearchManager asynchronously (to prevent many requests if multiple widgets are added at once, which is normal on the first render).

This is preventing CurrentRefinements from rendering notably (only widget which uses metadata)

## Result

metadata is caught using the same method as searchParameters, and injected via resultsState.

CurrentRefinements renders as expected in SSR.

fixes #2972

co-authored-by: samouss <samouss@users.noreply.github.com>
  • Loading branch information
Haroenv and samouss committed Oct 14, 2020
1 parent 22ecb3c commit be43b65
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 146 deletions.
2 changes: 2 additions & 0 deletions examples/server-side-rendering/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SearchBox,
Hits,
Configure,
CurrentRefinements,
} from 'react-instantsearch-dom';

class App extends Component {
Expand Down Expand Up @@ -41,6 +42,7 @@ class App extends Component {
>
<Configure hitsPerPage={3} />
<SearchBox />
<CurrentRefinements />
<RefinementList attribute="brand" />
<Hits />
</InstantSearch>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ Array [
</button>
</form>
</div>,
<div
className="ais-CurrentRefinements ais-CurrentRefinements--noRefinement"
>
<ul
className="ais-CurrentRefinements-list ais-CurrentRefinements-list--noRefinement"
/>
</div>,
<div
className="ais-RefinementList ais-RefinementList--noRefinement"
/>,
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,15 @@
},
{
"path": "packages/react-instantsearch/dist/umd/Dom.min.js",
"maxSize": "34.30 kB"
"maxSize": "34.45 kB"
},
{
"path": "packages/react-instantsearch-core/dist/umd/ReactInstantSearchCore.min.js",
"maxSize": "25.35 kB"
"maxSize": "25.50 kB"
},
{
"path": "packages/react-instantsearch-dom/dist/umd/ReactInstantSearchDOM.min.js",
"maxSize": "36.90 kB"
"maxSize": "37.05 kB"
},
{
"path": "packages/react-instantsearch-dom-maps/dist/umd/ReactInstantSearchDOMMaps.min.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ describe('createConnector', () => {
displayName: 'CoolConnector',
getProvidedProps: () => {},
getSearchParameters: () => null,
getMetadata: () => null,
})(() => null);

const onSearchParameters = jest.fn();
Expand All @@ -600,7 +601,8 @@ describe('createConnector', () => {
expect(onSearchParameters).toHaveBeenCalledWith(
expect.any(Function),
{ ais: context },
{ ...props, contextValue: context }
{ ...props, contextValue: context },
expect.any(Function)
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe('createInstantSearchManager', () => {
}

const resultsState = {
metadata: [],
rawResults: [
{
index: 'index',
Expand Down Expand Up @@ -120,34 +121,37 @@ describe('createInstantSearchManager', () => {
return;
}

const resultsState = [
{
_internalIndexId: 'index1',
rawResults: [
{
const resultsState = {
metadata: [],
results: [
{
_internalIndexId: 'index1',
rawResults: [
{
index: 'index1',
query: 'query1',
},
],
state: {
index: 'index1',
query: 'query1',
},
],
state: {
index: 'index1',
query: 'query1',
},
},
{
_internalIndexId: 'index2',
rawResults: [
{
{
_internalIndexId: 'index2',
rawResults: [
{
index: 'index2',
query: 'query2',
},
],
state: {
index: 'index2',
query: 'query2',
},
],
state: {
index: 'index2',
query: 'query2',
},
},
];
],
};

expect(Object.keys(searchClient.cache)).toHaveLength(0);

Expand Down Expand Up @@ -207,6 +211,7 @@ describe('createInstantSearchManager', () => {
}

const resultsState = {
metadata: [],
rawResults: [
{
index: 'indexName',
Expand Down Expand Up @@ -242,6 +247,7 @@ describe('createInstantSearchManager', () => {
}

const resultsState = {
metadata: [],
rawResults: [
{
index: 'indexName',
Expand Down Expand Up @@ -277,6 +283,7 @@ describe('createInstantSearchManager', () => {
}

const resultsState = {
metadata: [],
rawResults: [
{
index: 'indexName',
Expand Down Expand Up @@ -318,6 +325,7 @@ describe('createInstantSearchManager', () => {
indexName: 'index',
searchClient: createSearchClient(),
resultsState: {
metadata: [],
rawResults: [
{
index: 'indexName',
Expand All @@ -339,34 +347,37 @@ describe('createInstantSearchManager', () => {
const ism = createInstantSearchManager({
indexName: 'index',
searchClient: createSearchClient(),
resultsState: [
{
_internalIndexId: 'index1',
rawResults: [
{
resultsState: {
metadata: [],
results: [
{
_internalIndexId: 'index1',
rawResults: [
{
index: 'index1',
query: 'query1',
},
],
state: {
index: 'index1',
query: 'query1',
},
],
state: {
index: 'index1',
query: 'query1',
},
},
{
_internalIndexId: 'index2',
rawResults: [
{
{
_internalIndexId: 'index2',
rawResults: [
{
index: 'index2',
query: 'query2',
},
],
state: {
index: 'index2',
query: 'query2',
},
],
state: {
index: 'index2',
query: 'query2',
},
},
],
],
},
});

expect(ism.store.getState().results.index1.query).toBe('query1');
Expand Down
11 changes: 6 additions & 5 deletions packages/react-instantsearch-core/src/core/context.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { createContext } from 'react';
import { Store } from '../core/createStore';
import InstantSearch from '../widgets/InstantSearch';

export type InstantSearchContext = {
onInternalStateUpdate: (...args: any[]) => any;
createHrefForState: (...args: any[]) => string;
onSearchForFacetValues: (...args: any[]) => any;
onSearchStateChange: (...args: any[]) => any;
onSearchParameters: (...args: any[]) => any;
onInternalStateUpdate: InstantSearch['onWidgetsInternalStateUpdate'];
createHrefForState: InstantSearch['createHrefForState'];
onSearchForFacetValues: InstantSearch['onSearchForFacetValues'];
onSearchStateChange: InstantSearch['onSearchStateChange'];
onSearchParameters: InstantSearch['onSearchParameters'];
store: Store;
widgetsManager: any;
mainTargetedIndex: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ export function createConnectorWithoutContext(
ais: this.props.contextValue,
multiIndexContext: this.props.indexContextValue,
},
this.props
this.props,
connectorDesc.getMetadata && connectorDesc.getMetadata.bind(this)
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default function createInstantSearchManager({

const store = createStore({
widgets: initialState,
metadata: [],
metadata: hydrateMetadata(resultsState),
results: hydrateResultsState(resultsState),
error: null,
searching: false,
Expand Down Expand Up @@ -364,8 +364,8 @@ export default function createInstantSearchManager({
};
}

if (Array.isArray(results)) {
hydrateSearchClientWithMultiIndexRequest(client, results);
if (Array.isArray(results.results)) {
hydrateSearchClientWithMultiIndexRequest(client, results.results);
return;
}

Expand Down Expand Up @@ -478,8 +478,8 @@ export default function createInstantSearchManager({
return null;
}

if (Array.isArray(results)) {
return results.reduce(
if (Array.isArray(results.results)) {
return results.results.reduce(
(acc, result) => ({
...acc,
[result._internalIndexId]: new algoliasearchHelper.SearchResults(
Expand Down Expand Up @@ -610,3 +610,15 @@ export default function createInstantSearchManager({
skipSearch,
};
}

function hydrateMetadata(resultsState) {
if (!resultsState) {
return [];
}

return resultsState.metadata.map(datum => ({
...datum,
// add a value noop, which gets replaced once the widgets are mounted
value() {},
}));
}
3 changes: 2 additions & 1 deletion packages/react-instantsearch-core/src/widgets/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ class Index extends Component<InnerProps, State> {
ais: this.props.contextValue,
multiIndexContext: this.state.indexContext,
},
this.props
this.props,
undefined
);
}

Expand Down

0 comments on commit be43b65

Please sign in to comment.