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

Commit

Permalink
feat(ssr): update the SSR API (#2555)
Browse files Browse the repository at this point in the history
* feat(ssr): only expose findResultsState [PART-1] (#2536)

* feat(ssr): hydrate client [PART-2] (#2537)

* feat(ssr): update usage of the API [PART-3]
  • Loading branch information
samouss authored and Haroenv committed Jun 27, 2019
1 parent e209362 commit 925bdb8
Show file tree
Hide file tree
Showing 16 changed files with 862 additions and 640 deletions.
51 changes: 51 additions & 0 deletions examples/server-side-rendering/src/App.js
@@ -0,0 +1,51 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
InstantSearch,
RefinementList,
SearchBox,
Hits,
Configure,
} from 'react-instantsearch-dom';

class App extends Component {
static propTypes = {
indexName: PropTypes.string.isRequired,
searchClient: PropTypes.object.isRequired,
searchState: PropTypes.object,
resultsState: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.object),
PropTypes.object,
]),
};

static defaultProps = {
searchState: {},
};

state = {
searchState: this.props.searchState,
};

onSearchStateChange = nextSearchState =>
this.setState({ searchState: nextSearchState });

render() {
const { searchState } = this.state;

return (
<InstantSearch
{...this.props}
searchState={searchState}
onSearchStateChange={this.onSearchStateChange}
>
<Configure hitsPerPage={3} />
<SearchBox />
<RefinementList attribute="brand" />
<Hits />
</InstantSearch>
);
}
}

export default App;
@@ -1,10 +1,17 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { App } from './index';
import App from './App';

describe('Server-side rendering recipes', () => {
it('App renders without crashing', () => {
const component = renderer.create(<App />);
const props = {
indexName: 'index',
searchClient: {
search() {},
},
};

const component = renderer.create(<App {...props} />);

expect(component.toJSON()).toMatchSnapshot();
});
Expand Down
Expand Up @@ -66,15 +66,15 @@ exports[`Server-side rendering recipes App renders without crashing 1`] = `
</button>
</form>
</div>
<div
className="ais-RefinementList ais-RefinementList--noRefinement"
/>
<div
className="ais-Hits"
>
<ul
className="ais-Hits-list"
/>
</div>
<div
className="ais-RefinementList ais-RefinementList--noRefinement"
/>
</div>
`;
8 changes: 0 additions & 8 deletions examples/server-side-rendering/src/app/browser.js

This file was deleted.

42 changes: 0 additions & 42 deletions examples/server-side-rendering/src/app/index.js

This file was deleted.

14 changes: 14 additions & 0 deletions examples/server-side-rendering/src/browser.js
@@ -0,0 +1,14 @@
import React from 'react';
import { hydrate } from 'react-dom';
import { createApp } from './createApp';

const { App, props } = createApp();

const __APP_INITIAL_STATE__ = window.__APP_INITIAL_STATE__;

delete window.__APP_INITIAL_STATE__;

hydrate(
<App {...props} {...__APP_INITIAL_STATE__} />,
document.getElementById('root')
);
22 changes: 22 additions & 0 deletions examples/server-side-rendering/src/createApp.js
@@ -0,0 +1,22 @@
import algoliasearch from 'algoliasearch/lite';
import App from './App';

export const createApp = () => {
const indexName = 'instant_search';
const searchClient = algoliasearch(
'latency',
'6be0576ff61c053d5f9a3225e2a90f76'
);

const props = {
indexName,
searchClient,
};

return {
App,
props,
};
};

export default App;
40 changes: 29 additions & 11 deletions examples/server-side-rendering/src/server.js
Expand Up @@ -2,29 +2,47 @@ import { join } from 'path';
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { App, findResultsState } from './app';
import { findResultsState } from 'react-instantsearch-dom/server';
import { createApp } from './createApp';
import template from './template';

const server = express();

server.use('/assets', express.static(join(__dirname, 'assets')));

server.get('/', async (req, res) => {
const resultsState = await findResultsState(App);
const initialState = { resultsState };
const appString = renderToString(<App {...initialState} />);
server.get('/', async (_, res) => {
const { App, props } = createApp();

const searchState = {
query: 'iPhone',
page: 5,
refinementList: {
brand: ['Apple'],
},
};

const resultsState = await findResultsState(App, {
...props,
searchState,
});

const initialState = {
searchState,
resultsState,
};

const plainHTML = renderToString(<App {...props} {...initialState} />);

res.send(
template({
body: appString,
body: plainHTML,
title: 'Hello World from the server',
initialState: JSON.stringify(initialState),
})
);
});

server.listen(8080);

/* eslint-disable no-console */
console.log('listening on 8080');
/* eslint-enable no-console */
server.listen(8080, () => {
// eslint-disable-next-line no-console
console.log('Listening on: http://localhost:8080');
});
2 changes: 1 addition & 1 deletion examples/server-side-rendering/webpack.config.js
Expand Up @@ -39,7 +39,7 @@ module.exports = [
},
{
mode: 'development',
entry: ['@babel/polyfill', './src/app/browser.js'],
entry: ['babel-polyfill', './src/browser.js'],
output: {
path: path.join(__dirname, 'dist/assets'),
publicPath: '/',
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -131,7 +131,7 @@
},
{
"path": "packages/react-instantsearch/dist/umd/Connectors.min.js",
"maxSize": "41 kB"
"maxSize": "41.25 kB"
},
{
"path": "packages/react-instantsearch/dist/umd/Dom.min.js",
Expand All @@ -143,7 +143,7 @@
},
{
"path": "packages/react-instantsearch-dom/dist/umd/ReactInstantSearchDOM.min.js",
"maxSize": "53 kB"
"maxSize": "53.25 kB"
},
{
"path": "packages/react-instantsearch-dom-maps/dist/umd/ReactInstantSearchDOMMaps.min.js",
Expand Down

0 comments on commit 925bdb8

Please sign in to comment.