DefinitelyTyped/types/react-instantsearch/react-instantsearch-tests.tsx
Alex Young 1b05cbea62 update react-instantsearch-dom & core (#35940)
* update react-instantsearch-dom & core

* fixup! update react-instantsearch-dom & core

* fixup! update react-instantsearch-dom & core

* fixup! update react-instantsearch-dom & core
2019-06-05 14:35:52 -07:00

386 lines
10 KiB
TypeScript

import * as React from "react";
import { connectMenu, connectRefinementList, connectStateResults, SearchState } from "react-instantsearch/connectors";
import { InstantSearch, SearchBox, Index, Hits, Highlight, Menu } from "react-instantsearch/dom";
import { orderBy, omit, values } from 'lodash';
import { createInstantSearch } from "react-instantsearch-core";
// https://community.algolia.com/react-instantsearch/guide/Search_state.html
() => {
const searchState: SearchState = {
range: {
price: {
min: 20,
max: 3000
}
},
configure: {
aroundLatLng: true,
},
refinementList: {
fruits: ['lemon', 'orange']
},
hierarchicalMenu: {
products: 'Laptops > Surface'
},
menu: {
brands: 'Sony'
},
multiRange: {
rank: '2:5'
},
toggle: {
freeShipping: true
},
hitsPerPage: 10,
sortBy: 'mostPopular',
query: 'ora',
page: 2
};
};
() => {
const searchState: SearchState = {
query: 'ora', // shared state between all indices
page: 2, // shared state between all indices
indices: {
index1: {
configure: {
hitsPerPage: 3,
},
},
index2: {
configure: {
hitsPerPage: 10,
},
},
},
};
};
// https://community.algolia.com/react-instantsearch/guide/Custom_connectors.html
// TODO
// () => {
// const CoolWidget = createConnector({
// displayName: 'CoolWidget',
// getProvidedProps(props, searchState) {
// // Since the `queryAndPage` searchState entry isn't necessarily defined, we need
// // to default its value.
// const [query, page] = searchState.queryAndPage || ['', 0];
// // Connect the underlying component to the `queryAndPage` searchState entry.
// return {
// query,
// page,
// };
// },
// refine(props, searchState, newQuery, newPage) {
// // When the underlying component calls its `refine` prop, update the searchState
// // with the new query and page.
// return {
// // `searchState` represents the search state of *all* widgets. We need to extend it
// // instead of replacing it, otherwise other widgets will lose their
// // respective state.
// ...searchState,
// queryAndPage: [newQuery, newPage],
// };
// },
// })(props =>
// <div>
// The query is {props.query}, the page is {props.page}.
// {/*
// Clicking on this button will update the searchState to:
// {
// ...otherSearchState,
// query: 'algolia',
// page: 20,
// }
// */}
// <button onClick={() => props.refine('algolia', 20)} />
// {/*
// Clicking on this button will update the searchState to:
// {
// ...otherSearchState,
// query: 'instantsearch',
// page: 15,
// }
// */}
// <button onClick={() => props.refine('instantsearch', 15)} />
// </div>
// );
// };
// TODO
// () => {
// const Widget = () => null;
// const CoolWidget = createConnector({
// // displayName, getProvidedProps, refine
// getSearchParameters(searchParameters, props, searchState) {
// // Since the `queryAndPage` state entry isn't necessarily defined, we need
// // to default its value.
// const [query, page] = searchState.queryAndPage || ['', 0];
// // When the `queryAndPage` state entry changes, update the query and page of
// // search.
// return searchParameters
// .setQuery(query)
// .setPage(page);
// },
// })(Widget);
// };
// TODO
// () => {
// const Widget = () => null;
// const CoolWidget = createConnector({
// // displayName, getProvidedProps, refine, getSearchParameters
// getMetadata(props, searchState) {
// // Since the `queryAndPage` searchState entry isn't necessarily defined, we need
// // to default its value.
// const [query, page] = searchState.queryAndPage || ['', 0];
// const filters = [];
// if (query !== '') {
// filters.push({
// // Unique identifier for this filter.
// key: `queryAndPage.query`,
// // String label (or node) that should appear in the CurrentRefinements
// // component.
// label: `Query: ${query}`,
// // Describes how clearing this filter affects the InstantSearch searchState.
// // In our case, clearing the query just resets it to an empty string
// // without affecting the page.
// clear: nextSearchState => {
// return {
// ...nextSearchState,
// // Do not depend on the current `searchState` here. Since filters can be
// // cleared in batches, the `searchState` parameter is not up-to-date when
// // this method is called.
// queryAndPage: ['', nextSearchState.queryAndPage[1]],
// };
// },
// });
// }
// if (page !== 0) {
// filters.push({
// key: `queryAndPage.page`,
// label: `Page: ${page}`,
// clear: nextSearchState => {
// return {
// ...nextSearchState,
// queryAndPage: [nextSearchState.queryAndPage[0], 0],
// };
// },
// });
// }
// return {
// // This widget manipulates the `queryAndPage` state entry.
// id: 'queryAndPage',
// filters,
// };
// },
// })(Widget);
// };
// TODO
// () => {
// const Widget = () => null;
// const CoolWidget = createConnector({
// // displayName, getProvidedProps, refine, getSearchParameters, getMetadata
// searchForFacetValues(props, searchState, nextRefinement) {
// return {facetName: props.attribute, query: nextRefinement};
// },
// })(Widget);
// };
// TODO
// () => {
// const Widget = () => null;
// const CoolWidget = createConnector({
// // displayName, getProvidedProps, refine, getSearchParameters, getMetadata
// cleanUp(props, searchState) {
// return omit('queryAndPage', searchState);
// },
// })(Widget);
// };
// https://community.algolia.com/react-instantsearch/guide/Conditional_display.html
() => {
const Content = connectStateResults(
({ searchState }) =>
searchState && searchState.query
? <div>
The query {searchState.query} exists
</div>
: <div>No query</div>
);
};
() => {
const Content = connectStateResults(
({ searchState, searchResults }) =>
searchResults && searchResults.nbHits !== 0
? <div>Some results</div>
: <div>
No results has been found for {searchState.query}
</div>
);
};
() => {
const Content = connectStateResults(
({ error }) =>
error ? <div>Some error</div> : <div>No error</div>
);
};
() => {
const Content = connectStateResults(
({ searching }) =>
searching ? <div>We are searching</div> : <div>Search finished</div>
);
};
() => {
const Content = connectStateResults(
({ searchingForFacetValues }) =>
searchingForFacetValues ? <div>We are searching</div> : <div>Search finished</div>
);
};
() => {
const App = () => (
<InstantSearch indexName="first" searchClient={{}}>
<SearchBox />
<AllResults>
<div>
<Index indexName="first">
<IndexResults>
<div>
<div>first: </div>
<Hits />
</div>
</IndexResults>
</Index>
<Index indexName="second">
<IndexResults>
<div>
<div>second: </div>
<Hits />
</div>
</IndexResults>
</Index>
<Index indexName="third">
<IndexResults>
<div>
<div>third: </div>
<Hits />
</div>
</IndexResults>
</Index>
</div>
</AllResults>
</InstantSearch>
);
const IndexResults = connectStateResults(
({ searchState, searchResults, children }) =>
searchResults && searchResults.nbHits !== 0 ? (
children as React.ReactElement
) : (
<div>
No results has been found for {searchState.query} and index{' '}
{searchResults ? searchResults.index : ''}
</div>
)
);
const AllResults = connectStateResults(({ allSearchResults, children }) => {
const hasResults =
allSearchResults &&
values(allSearchResults).some(results => results.nbHits > 0);
return !hasResults ? (
<div>
<div>No results in category, products or brand</div>
<Index indexName="first" />
<Index indexName="second" />
<Index indexName="third" />
</div>
) : (
children as React.ReactElement
);
});
};
// https://github.com/algolia/react-instantsearch/blob/master/packages/react-instantsearch-dom/src/widgets/InstantSearch.js
() => {
const InstantSearch = createInstantSearch(
() => ({}),
{
Root: 'div',
props: {
className: 'ais-InstantSearch__root',
},
}
);
<InstantSearch />;
};
() => {
const RefinementListWithSearchBox = connectRefinementList(props => {
const values = props.items.map(item => {
const label = item._highlightResult
? <Highlight attribute="label" hit={item}/>
: item.label;
return (
<li key={item.label}>
<span onClick={() => props.refine(item.value)}>
{label} {item.isRefined ? '- selected' : ''}
</span>
</li>
);
});
return (
<div>
<input type="search" onInput={e => props.searchForItems((e.target as HTMLInputElement).value)}/>
<ul>{values}</ul>
</div>
);
});
return <RefinementListWithSearchBox attribute="products" />;
};
// https://community.algolia.com/react-instantsearch/guide/Virtual_widgets.html
() => {
const VirtualMenu = connectMenu(() => null);
const Hoodies = () => <VirtualMenu attribute="clothes" defaultRefinement="hoodies" />;
const App = () => (
<InstantSearch
indexName="..."
searchClient={{}}
>
<SearchBox defaultRefinement="hi" />
<Hoodies />
<Menu attribute="fruits" defaultRefinement="Orange" />
</InstantSearch>
);
};