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 => //
// The query is {props.query}, the page is {props.page}. // {/* // Clicking on this button will update the searchState to: // { // ...otherSearchState, // query: 'algolia', // page: 20, // } // */} //
// ); // }; // 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 ?
The query {searchState.query} exists
:
No query
); }; () => { const Content = connectStateResults( ({ searchState, searchResults }) => searchResults && searchResults.nbHits !== 0 ?
Some results
:
No results has been found for {searchState.query}
); }; () => { const Content = connectStateResults( ({ error }) => error ?
Some error
:
No error
); }; () => { const Content = connectStateResults( ({ searching }) => searching ?
We are searching
:
Search finished
); }; () => { const Content = connectStateResults( ({ searchingForFacetValues }) => searchingForFacetValues ?
We are searching
:
Search finished
); }; () => { const App = () => (
first:
second:
third:
); const IndexResults = connectStateResults( ({ searchState, searchResults, children }) => searchResults && searchResults.nbHits !== 0 ? ( children as React.ReactElement ) : (
No results has been found for {searchState.query} and index{' '} {searchResults ? searchResults.index : ''}
) ); const AllResults = connectStateResults(({ allSearchResults, children }) => { const hasResults = allSearchResults && values(allSearchResults).some(results => results.nbHits > 0); return !hasResults ? (
No results in category, products or brand
) : ( 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', }, } ); ; }; () => { const RefinementListWithSearchBox = connectRefinementList(props => { const values = props.items.map(item => { const label = item._highlightResult ? : item.label; return (
  • props.refine(item.value)}> {label} {item.isRefined ? '- selected' : ''}
  • ); }); return (
    props.searchForItems((e.target as HTMLInputElement).value)}/>
      {values}
    ); }); return ; }; // https://community.algolia.com/react-instantsearch/guide/Virtual_widgets.html () => { const VirtualMenu = connectMenu(() => null); const Hoodies = () => ; const App = () => ( ); };