Skip to content

Commit

Permalink
docs(guides): add a guide explaining how to use react-router with ris (
Browse files Browse the repository at this point in the history
…#1527)

also re-document our onStateChange, createURL and state props on InstantSearch

BREAKING CHANGE:
urlSync/Thresold should not be use anymore. If the url synchronisation is needed please follow the url-routing section of the advanced topics guide.
  • Loading branch information
mthuret authored and vvo committed Nov 10, 2016
1 parent d02fef2 commit a947404
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 24 deletions.
1 change: 0 additions & 1 deletion docgen/src/examples/media/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default function App() {
appId="latency"
apiKey="6be0576ff61c053d5f9a3225e2a90f76"
indexName="movies"
urlSync
>
<div>
<Header/>
Expand Down
82 changes: 63 additions & 19 deletions docgen/src/guides/advanced-topics.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,31 +73,75 @@ const ConnectedMenu = connectMenu(props => {
<ConnectedMenu attributeName="category"/>
```

## How to synchronize the url with the search
## URL Routing

The InstantSearch component features a complete URL synchronization solution. Whenever a widget's state changes, the URL will be updated to reflect the new state of the search UI. This has two main benefits:
One thing that could be nice to have is whenever a widget's state changes, the URL would be updated to reflect the new state of the search UI.
Doing so has two main benefits:

* the user can use the browser's back and forward buttons to navigate back and forth between the different states of the search.
* the user can bookmark, copy and share a custom search URL.

To activate this feature, you need to pass the `urlSync` props when instantiating the InstantSearch component.
To be able to do that, you will need to provide three props to the [InstantSearch root component](/components/InstantSearch.html).

Here's an example
* onStateChange(nextState): this a function that is called every time the InstantSearch state is being updated.
* state: an object that is the current state of InstantSearch
* createURL(state): this function is needed for every widgets that will render a link. It expects a string in return.
This function while provided to every widgets and connectors is only useful if you are in a browser context.

```jsx
<InstantSearch
appId="appId"
apiKey="apiKey"
indexName="indexName"
urlSync
>
</InstantSearch>
```

**Location Debouncing**

Since UI updates can happen in quick succession, for instance when the user types in a query,
the new locations are debounced. The treshold prop controls how long the component should wait between
state changes before pushing a new location instead of replacing the old one.
Here's an example showing you how to use [react-router](https://github.com/ReactTraining/react-router) with react-instantsearch.

```javascript
import React, {Component} from 'react';
import {
InstantSearch
} from 'react-instantsearch/dom';
import {withRouter} from 'react-router';
import qs from 'qs';

class App extends Component {
constructor (props) {
super(props);
this.state = {state: {...qs.parse(this.props.router.location.query)}}; //we initialize the state by parsing the url
}

/*
push the new state to the react-router history. The threshold is there to specify how long we should wait between
state changes before pushing a new location instead of replacing the old one. This is a very basic implementation you
might want to perform advanced behaviors like removing empty values from the url or being able to keep others query params.
*/
onStateChange = (nextState) => {
const THRESHOLD = 700;
const newPush = Date.now();
this.setState({lastPush: newPush, state: nextState}); //the current state is saved to be given as the state props of InstantSearch root component
if (this.state.lastPush && newPush - this.state.lastPush <= THRESHOLD) {
this.props.router.replace(nextState ? `?${qs.stringify(nextState)}` : '');
} else {
this.props.router.push(nextState ? `?${qs.stringify(nextState)}` : '');
}
};

/*
This is the function that will be provided to every widgets and connectors. It allows you to be able to create a link.
*/
createURL = (state) => {
return `?${qs.stringify(state)}`;
};

render() {
return (
<InstantSearch
appId="appId"
apiKey="apiKey"
indexName="indexName"
state={this.state.state}
onStateChange={this.onStateChange.bind(this)}
createURL={this.createURL.bind(this)}
>
</InstantSearch>
);
}
}

export default withRouter(App);
```

5 changes: 3 additions & 2 deletions packages/react-instantsearch/src/core/InstantSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ function validateNextProps(props, nextProps) {
* @propType {string} apiKey - Your Algolia Search-Only API key.
* @propType {string} indexName - The index in which to search.
* @propType {object} [searchParameters] - Object containing query parameters to be sent to Algolia. It will be overriden by the search parameters resolved via the widgets. Typical use case: setting the distinct setting is done by providing an object like: `{distinct: 1}`. For more information about the kind of object that can be provided on the [official API documentation](https://www.algolia.com/doc/rest-api/search#full-text-search-parameters). See [Configuring Algolia search parameters](/guides/advanced-topics.html#how-to-configure-algolia-search-parameters).
* @propType {bool=false} urlSync - Enables automatic synchronization of widgets state to the URL. See [URL Synchronization](/guides/advanced-topics.html#how-to-synchronize-the-url-with-the-search).
* @propType {number=700} threshold - Threshold in milliseconds above which new locations will be pushed to the history, instead of replacing the previous one. See [Location Debouncing](guides/advanced-topics.html#how-to-synchronize-the-url-with-the-search).
* @propType {func} onStateChange - See [URL Routing](/guides/advanced-topics.html#url-routing).
* @propType {object} state - See [URL Routing](/guides/advanced-topics.html#url-routing).
* @propType {func} createURL - See [URL Routing](/guides/advanced-topics.html#url-routing).
* @example
* import {InstantSearch, SearchBox, Hits} from 'react-instantsearch/dom';
*
Expand Down
2 changes: 0 additions & 2 deletions stories/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const Wrap = props =>
appId="latency"
apiKey="6be0576ff61c053d5f9a3225e2a90f76"
indexName="ikea"
urlSync={false}
>
{props.children}
</InstantSearch>;
Expand Down Expand Up @@ -53,7 +52,6 @@ const WrapWithHits = ({children, searchBox = true, hasPlayground = false, linked
appId="latency"
apiKey="6be0576ff61c053d5f9a3225e2a90f76"
indexName="ikea"
urlSync={false}
>
<div>
<div className="container widget-container">
Expand Down

0 comments on commit a947404

Please sign in to comment.