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

Commit

Permalink
fix(compat): upgrade Next.js example lifecycles (#2379)
Browse files Browse the repository at this point in the history
* fix(compat): update Next example

* fix(compat): use last Next router
  • Loading branch information
samouss authored and Haroenv committed Jun 27, 2019
1 parent f390c17 commit 45939bc
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 160 deletions.
72 changes: 40 additions & 32 deletions examples/next/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,80 @@
import { isEqual } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import Router from 'next/router';
import { withRouter } from 'next/router';
import qs from 'qs';
import { Head, App, findResultsState } from '../components';

const updateAfter = 700;

const createURL = state => `?${qs.stringify(state)}`;

const searchStateToUrl = searchState =>
const pathToSearchState = path =>
path.includes('?') ? qs.parse(path.substring(path.indexOf('?') + 1)) : {};

const searchStateToURL = searchState =>
searchState ? `${window.location.pathname}?${qs.stringify(searchState)}` : '';

export default class extends React.Component {
class Page extends React.Component {
static propTypes = {
router: PropTypes.object.isRequired,
resultsState: PropTypes.object,
searchState: PropTypes.object,
};

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

/*
nextjs params.query doesn't handle nested objects
once it does, params.query could be used directly here, but also inside the constructor
to initialize the searchState.
*/
static async getInitialProps(params) {
const searchState = params.asPath.includes('?')
? qs.parse(params.asPath.substring(params.asPath.indexOf('?') + 1))
: {};
static async getInitialProps({ asPath }) {
const searchState = pathToSearchState(asPath);
const resultsState = await findResultsState(App, { searchState });
return { resultsState, searchState };

return {
resultsState,
searchState,
};
}

static getDerivedStateFromProps(props, state) {
if (!isEqual(state.lastRouter, props.router)) {
return {
searchState: pathToSearchState(props.router.asPath),
lastRouter: props.router,
};
}

return null;
}

onSearchStateChange = searchState => {
clearTimeout(this.debouncedSetState);

this.debouncedSetState = setTimeout(() => {
const href = searchStateToUrl(searchState);
Router.push(href, href, {
const href = searchStateToURL(searchState);

this.props.router.push(href, href, {
shallow: true,
});
}, updateAfter);

this.setState({ searchState });
};

componentDidMount() {
this.setState({ searchState: qs.parse(window.location.search.slice(1)) });
}

componentWillReceiveProps() {
// @TODO: probably derived state
this.setState({ searchState: qs.parse(window.location.search.slice(1)) });
}

render() {
return (
<div>
<Head title="Home" />
<div>
<App
searchState={this.state.searchState}
resultsState={this.props.resultsState}
onSearchStateChange={this.onSearchStateChange}
createURL={createURL}
/>
</div>
<App
searchState={this.state.searchState}
resultsState={this.props.resultsState}
onSearchStateChange={this.onSearchStateChange}
createURL={createURL}
/>
</div>
);
}
}

export default withRouter(Page);
188 changes: 93 additions & 95 deletions examples/next/tests/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,107 +2,105 @@

exports[`Next app recipes App renders without crashing 1`] = `
<div>
<div>
<div
className="ais-InstantSearch__root"
>
<header>
<h1>
React InstantSearch + Next.Js
</h1>
<div
className="ais-SearchBox"
<div
className="ais-InstantSearch__root"
>
<header>
<h1>
React InstantSearch + Next.Js
</h1>
<div
className="ais-SearchBox"
>
<form
action=""
className="ais-SearchBox-form"
noValidate={true}
onReset={[Function]}
onSubmit={[Function]}
role="search"
>
<form
action=""
className="ais-SearchBox-form"
noValidate={true}
onReset={[Function]}
onSubmit={[Function]}
role="search"
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
autoFocus={false}
className="ais-SearchBox-input"
maxLength="512"
onChange={[Function]}
placeholder="Search here…"
required={true}
spellCheck="false"
type="search"
value=""
/>
<button
className="ais-SearchBox-submit"
title="Submit your search query."
type="submit"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
autoFocus={false}
className="ais-SearchBox-input"
maxLength="512"
onChange={[Function]}
placeholder="Search here…"
required={true}
spellCheck="false"
type="search"
value=""
/>
<button
className="ais-SearchBox-submit"
title="Submit your search query."
type="submit"
<svg
className="ais-SearchBox-submitIcon"
height="10"
viewBox="0 0 40 40"
width="10"
xmlns="http://www.w3.org/2000/svg"
>
<svg
className="ais-SearchBox-submitIcon"
height="10"
viewBox="0 0 40 40"
width="10"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M26.804 29.01c-2.832 2.34-6.465 3.746-10.426 3.746C7.333 32.756 0 25.424 0 16.378 0 7.333 7.333 0 16.378 0c9.046 0 16.378 7.333 16.378 16.378 0 3.96-1.406 7.594-3.746 10.426l10.534 10.534c.607.607.61 1.59-.004 2.202-.61.61-1.597.61-2.202.004L26.804 29.01zm-10.426.627c7.323 0 13.26-5.936 13.26-13.26 0-7.32-5.937-13.257-13.26-13.257C9.056 3.12 3.12 9.056 3.12 16.378c0 7.323 5.936 13.26 13.258 13.26z"
/>
</svg>
</button>
<button
className="ais-SearchBox-reset"
hidden={true}
title="Clear the search query."
type="reset"
<path
d="M26.804 29.01c-2.832 2.34-6.465 3.746-10.426 3.746C7.333 32.756 0 25.424 0 16.378 0 7.333 7.333 0 16.378 0c9.046 0 16.378 7.333 16.378 16.378 0 3.96-1.406 7.594-3.746 10.426l10.534 10.534c.607.607.61 1.59-.004 2.202-.61.61-1.597.61-2.202.004L26.804 29.01zm-10.426.627c7.323 0 13.26-5.936 13.26-13.26 0-7.32-5.937-13.257-13.26-13.257C9.056 3.12 3.12 9.056 3.12 16.378c0 7.323 5.936 13.26 13.258 13.26z"
/>
</svg>
</button>
<button
className="ais-SearchBox-reset"
hidden={true}
title="Clear the search query."
type="reset"
>
<svg
className="ais-SearchBox-resetIcon"
height="10"
viewBox="0 0 20 20"
width="10"
xmlns="http://www.w3.org/2000/svg"
>
<svg
className="ais-SearchBox-resetIcon"
height="10"
viewBox="0 0 20 20"
width="10"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.114 10L.944 2.83 0 1.885 1.886 0l.943.943L10 8.113l7.17-7.17.944-.943L20 1.886l-.943.943-7.17 7.17 7.17 7.17.943.944L18.114 20l-.943-.943-7.17-7.17-7.17 7.17-.944.943L0 18.114l.943-.943L8.113 10z"
/>
</svg>
</button>
</form>
</div>
</header>
<content>
<menu>
<div
className="ais-RefinementList ais-RefinementList--noRefinement"
<path
d="M8.114 10L.944 2.83 0 1.885 1.886 0l.943.943L10 8.113l7.17-7.17.944-.943L20 1.886l-.943.943-7.17 7.17 7.17 7.17.943.944L18.114 20l-.943-.943-7.17-7.17-7.17 7.17-.944.943L0 18.114l.943-.943L8.113 10z"
/>
</svg>
</button>
</form>
</div>
</header>
<content>
<menu>
<div
className="ais-RefinementList ais-RefinementList--noRefinement"
/>
</menu>
<results>
<div
className="ais-Hits"
>
<ul
className="ais-Hits-list"
/>
</menu>
<results>
<div
className="ais-Hits"
>
<ul
className="ais-Hits-list"
/>
</div>
</results>
</content>
<footer>
<div>
See
<a
href="https://github.com/algolia/react-instantsearch/tree/master/examples/next"
>
source code
</a>
on github
</div>
</footer>
</div>
</results>
</content>
<footer>
<div>
See
<a
href="https://github.com/algolia/react-instantsearch/tree/master/examples/next"
>
source code
</a>
on github
</div>
</footer>
</div>
</div>
`;
2 changes: 1 addition & 1 deletion examples/next/tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import App from '../pages/index';

describe('Next app recipes', () => {
it('App renders without crashing', () => {
const component = renderer.create(<App searchState={{}} />);
const component = renderer.create(<App searchState={{}} router={{}} />);

expect(component.toJSON()).toMatchSnapshot();
});
Expand Down
Loading

0 comments on commit 45939bc

Please sign in to comment.