
ReactiveList creates a data-driven result list UI component. This list can reactively update itself based on changes in other components or changes in the database itself.
Example uses:
- showing a feed of results based on the applied search criteria.
Usage
Basic Usage
<ReactiveList
	componentId="SearchResult"
	react={{
		and: ['CitySensor', 'SearchSensor'],
	}}
	renderItem={res => <div>{res.title}</div>}
/>Usage With All Props
<ReactiveList
    componentId="SearchResult"
    dataField="ratings"
    pagination={false}
    paginationAt="bottom"
    pages={5}
    sortBy="desc"
    size={10}
    loader="Loading Results.."
    showResultStats={true}
    renderItem={res => <div>{res.title}</div>}
    renderResultStats={function(stats) {
    	return `Showing ${stats.displayedResults} of total ${stats.numberOfResults} in ${
    		stats.time
    	} ms`;
    }}
    react={{
    	and: ['CitySensor', 'SearchSensor'],
    }}
    endpoint={{
      url:"https://appbase-demo-ansible-abxiydt-arc.searchbase.io/recipes-demo/_reactivesearch.v3", //mandatory
      headers:{
        // relevant headers
      },
      method: 'POST'
    }}    
/>Props
- 
componentId Stringunique identifier of the component, can be referenced in other components'reactprop.
- 
endpoint Object[optional] endpoint prop provides the ability to query a user-defined backend service for this component, overriding the data endpoint configured in the ReactiveBase component. Works only whenenableAppbaseistrue. Accepts the following properties:- url String[Required] URL where the data cluster is hosted.
- headers Object[optional]
 set custom headers to be sent with each server request as key/value pairs.
- method String[optional]
 set method of the API request.
- body Object[optional]
 request body of the API request. When body isn't set and method is POST, the request body is set based on the component's configured props.
 - Overrides the endpoint property defined in ReactiveBase.
- If required, use transformResponseprop to transform response in component-consumable format.
 
- url 
- 
dataField Stringdata field to be connected to the component's UI view. It is useful for providing a sorting context.
- 
aggregationField String[optional] One of the most important use-cases this enables is showingDISTINCTresults (useful when you are dealing with sessions, events and logs type data). It utilizescomposite aggregationswhich are newly introduced in ES v6 and offer vast performance benefits over a traditional terms aggregation. You can read more about it over here. You can accessaggregationDatausing render prop as shown:<ReactiveList aggregationField="original_title.keyword" render={({aggregationData}) => {...}} />If you are using an app with elastic search version less than 6, then defining this prop will result in error and you need to handle it manually using renderError prop. It is possible to override this query by providing defaultQuery.Note: This prop has been marked as deprecated starting v3.18.0. Please use the distinctFieldprop instead.
- 
aggregationSize To set the number of buckets to be returned by aggregations. Note: This prop is only applicable when enableAppbaseis set totrue.
- 
excludeFields String Array[optional] fields to be excluded in search results.
- 
includeFields String Array[optional] fields to be included in search results.
- 
scrollTarget StringorObject[optional] acceptsidor the dom node of the container you wish to apply infinite loading on. Note: The container should be scrollable.
- 
scrollOnChange Boolean[optional] Enables you to customise the window scrolling experience on query change. Defaults totruei.e. The window will scroll to top in case of the query change, which can be triggered by change in pagination, change in filters or search value, etc. When set tofalse, scroll position will stay intact.
- 
pagination Boolean[optional] Defaults tofalse, When set totrue, a pagination based list view with page numbers will appear.
- 
infiniteScroll Boolean[optional] Defaults totrue, When set totrue, an infinite scroll based view will appear.
- 
paginationAt String[optional] Determines the position where to show the pagination, only applicable when pagination prop is set totrue. Accepts one oftop,bottomorbothas valid values. Defaults tobottom.
- 
pages Number[optional] number of user selectable pages to be displayed when pagination is enabled. Defaults to 5.
- 
currentPage Number[optional] can be used to set the default page number for initial render.
- 
sortBy String[optional] sort the results by eitherascordescorder. It is an alternative tosortOptions, both can't be used together.
- 
sortOptions Object Array[optional] an alternative to thesortByprop,sortOptionscreates a sorting view in the ReactiveList component's UI. Each array element is an object that takes three keys:- label- label to be displayed in the UI.
- dataField- data field to use for applying the sorting criteria on.
- sortBy- specified as either- ascor- desc.
 
- 
defaultSortOption String[optional] accepts the label of the desired sort option to set default sort value from givensortOptionsarray.
- 
size Number[optional] number of results to show per view. Defaults to 10.
- 
loader String or JSX[optional] display to show the user while the data is loading, acceptsStringorJSXmarkup.
- 
showLoader Boolean[optional] defaults totrue, if set tofalsethen the ReactiveList will not display the default loader.
- 
showResultStats Boolean[optional] whether to show result stats in the form of results found and time taken. Defaults totrue.
- 
showExport Boolean[optional] renders UI that lets exporting data into a CSV and JSON document. Defaults totrue. The export options' UI can be styled by passingexportkey ininnerClassprop.
- 
react Object[optional] a dependency object defining how this component should react based on the state changes in the sensor components.
- 
URLParams Boolean[optional] when set adds the current page number to the url. Only works whenpaginationis enabled.
- 
defaultQuery Function[optional] applies a default query to the result component. This query will be run when no other components are being watched (via React prop), as well as in conjunction with the query generated from the React prop. The function should return a query. Read more about it here.
- 
renderItem Function[optional] returns a list element object to be rendered based on theresdata object. This callback function prop is called for each data item rendered in the ReactiveList component's view. For example,renderItem = { function(res) { return ( <a className="full_row single-record single_record_for_clone" key={res._id}> <div className="text-container full_row" style={{ paddingLeft: '10px' }}> <div className="text-head text-overflow full_row"> <span className="text-head-info text-overflow"> {res.name ? res.name : ''} - {res.brand ? res.brand : ''} </span> <span className="text-head-city">{res.brand ? res.brand : ''}</span> </div> <div className="text-description text-overflow full_row"> <ul className="highlight_tags"> {res.price ? `Priced at $${res.price}` : 'Free Test Drive'} </ul> </div> </div> </a> ); }, };
- 
render Function[optional] A function returning the UI you want to render based on your results. This function receives a list of parameters and expects to return aJSX. Read more about it here.Note: Either renderItemorrenderis required in ReactiveList for rendering the data.
- 
renderError String or JSX or Function[optional] can be used to render an error message in case of any error.renderError={(error) => ( <div> Something went wrong!<br/>Error details<br/>{error} </div> ) }
- 
renderResultStats Function[optional] renders custom result stats using a callback function that takesstatsobject as parameter and expects it to return a string or JSX.statsobject contains following properties- numberOfResults:- numberTotal number of results found
- numberOfPages:- numberTotal number of pages found based on current page size
- currentPage:- numberCurrent page number for which data is being rendered
- time:- numberTime taken to find total results (in ms)
- displayedResults:- numberNumber of results displayed in current view
- hidden:- numberTotal number of hidden results found
- promoted:- numberTotal number of promoted results found
 renderResultStats = { function(stats) { return `Showing ${stats.displayedResults} of total ${stats.numberOfResults} in ${ stats.time } ms`; }, };
- 
renderNoResults Function[optional] show custom message or component when no results found.
- 
renderPagination String or JSX or Function[optional] can be used to render custom pagination.- 
pages:numberNumber of pages to be displayed
- 
totalPages:numberTotal number of pages found based on current page size
- 
currentPage:numberCurrent page number for which data is being rendered
- 
setPage:functionFunction use to set the currentPage
- 
fragmentName:stringcomponentIdof the Result component for setting url params for eg:<a href={`?${fragmentName}=${pageNumber}`}>{pageNumber}</a>
 renderPagination={({ pages, totalPages, currentPage, setPage, setSize }) => { const selectPage = Number.isFinite(totalPages) && ( <select value={currentPage + 1} onChange={e => setPage(parseInt(e.target.value, 10))} > {new Array(totalPages).fill(0).map((_, i) => ( <option value={i}>{i + 1}</option> ))} </select> ); return selectPage; }
- 
- 
renderExport Function[optional] renders custom export options UI using a callback function that takes a object parameter as parameter and expects it to return a string or JSX. The parameter object contains following properties- triggerExportCSV:- functioncallback to trigger export of data to a CSV document.
- triggerExportJSON:- functioncallback to trigger export of data to a JSON document.
 renderExport={ ({ triggerExportCSV, triggerExportJSON }) => (<div> Custom Export <button onClick={triggerExportCSV}>CSV 🔢</button> <button onClick={triggerExportJSON}>JSON ❤️</button> </div>) }
- 
onData Function[optional] gets triggered after data changes, which returns an object with these properties:data,promotedData,customData,rawData&resultStats.
- 
onError Function[optional] gets triggered in case of an error and provides theerrorobject, which can be used for debugging or giving feedback to the user if needed.
- 
onPageChange Function[optional] executes when the current page is changed. If not defined,windowwill be scrolled to the top of the page.
- 
onPageClick Function[optional] accepts a function which is invoked with the updated page value when a pagination button is clicked. For example if 'Next' is clicked with the current page number as '1', you would receive the value '2' as the function parameter.
Note:
The fundamental difference between
onPageChangeandonPageClickis thatonPageClickis only called on a manual interaction with the pagination buttons, whereas,onPageChangewould also be invoked if some other side effects caused the results to update which includes updating filters, queries or changing pages. The behaviour of these two may change in the future versions as we come up with a better API.
- 
distinctField String[optional] This prop returns only the distinct value documents for the specified field. It is equivalent to theDISTINCTclause in SQL. It internally uses the collapse feature of Elasticsearch. You can read more about it over here.
- 
distinctFieldConfig Object[optional] This prop allows specifying additional options to thedistinctFieldprop. Using the allowed DSL, one can specify how to return K distinct values (default value of K=1), sort them by a specific order, or return a second level of distinct values.distinctFieldConfigobject corresponds to theinner_hitskey's DSL. You can read more about it over here.
<ReactiveList
	....
	distinctField="authors.keyword"
	distinctFieldConfig={{
		inner_hits: {
			name: 'most_recent',
			size: 5,
			sort: [{ timestamp: 'asc' }],
		},
		max_concurrent_group_searches: 4,
	}}
/>> Note: In order to use the `distinctField` and `distinctFieldConfig` props, the `enableAppbase` prop must be set to true in `ReactiveBase`.Sub Components
- ResultCardsWrapper
A wrapper component for ResultCardcomponents to render a card based layout. Read more about the usage here.
- ResultListWrapper
A wrapper component for ResultListcomponents to render a list based layout. Read more about the usage here.
Demo
Styles
ReactiveList component supports innerClass prop with the following keys:
- resultsInfo
- sortOptions
- resultStats
- noResults
- button
- pagination
- active
- list
- poweredBy
- export
Read more about it here.
Extending
ReactiveList component can be extended to
- customize the look and feel with className,style,
- render individual result data items using renderItem,
- render the entire data using render.
- connect with external interfaces using onQueryChange.
<ReactiveList
  ...
  className="custom-class"
  style={{"paddingBottom": "10px"}}
  renderItem={
    function(res) {
      return(
        <div>
          { res.data }
        </div>
      )
    }
  }
  onQueryChange={
    function(prevQuery, nextQuery) {
      // use the query with other js code
      console.log('prevQuery', prevQuery);
      console.log('nextQuery', nextQuery);
    }
  }
/>- className StringCSS class to be injected on the component container.
- style ObjectCSS Styles to be applied to the ReactiveList component.
- renderItem Function[optional] a callback function where user can define how to render the view based on the data changes.
- render Function[optional] an alternative callback function torenderItem, where user can define how to render the view based on all the data changes.
 It accepts an object with these properties:- loading:- booleanindicates that the query is still in progress
- error:- objectAn object containing the error info
- data:- arrayAn array of results obtained from combining- promotedresults along with the- hits.
- aggregationData- arrayAn array of aggregations buckets. Each bucket would have a- top_hitsproperty if you're using Elasticsearch top hits aggregations in- defaultQueryprop.
- promotedData:- array
 An array of promoted results obtained from the applied query. [Read More](/docs/search/rules/) > Note: > > `data` and `promotedData` results has a property called `_click_id` which can be used with triggerClickAnalytics to register the click analytics info.- customData- objectCustom data set in the query rule when appbase.io is used as backend. Read More
- rawData- objectAn object of raw response as-is from elasticsearch query.
- resultStats:- objectAn object with the following properties which can be helpful to render custom stats:- numberOfResults:- numberTotal number of results found
- numberOfPages:- numberTotal number of pages found based on current page size
- currentPage:- numberCurrent page number for which data is being rendered
- time:- numberTime taken to find total results (in ms)
- displayedResults:- numberNumber of results displayed in current view
- hidden:- numberTotal number of hidden results found
- promoted:- numberTotal number of promoted results found
 
- loadMore:- functionA callback function to be called to load the next page of results into the view. The callback function is only applicable in the case of infinite loading view (i.e.- infiniteScrollprop set to- true).
- triggerClickAnalytics:- functionA function which can be called to register a click analytics. Read More
- triggerExportCSV:- functioncallback to trigger export of data to a CSV document.
- triggerExportJSON:- functioncallback to trigger export of data to a JSON document.
 
<ReactiveList
	showLoader={false} // Hides the default loader
	render={({ loading, error, data }) => {
		if (loading) {
			return <div>Fetching Results.</div>;
		}
		if (error) {
			return <div>Something went wrong! Error details {JSON.stringify(error)}</div>;
		}
		return (
			<ul>
				{data.map(item => (
					<li>
						{item.title}
						{/* Render UI */}
					</li>
				))}
			</ul>
		);
	}}
/>Or you can also use render function as children
<ReactiveList>
    {
        ({
            loading,
            error,
            data,
            promotedData,
            rawData,
            resultStats,
            handleLoadMore,
            triggerClickAnalytics
        }) => (
            // return UI to be rendered
        )
    }
</ReactiveList>- 
onQueryChange Functionis a callback function which accepts component's prevQuery and nextQuery as parameters. It is called everytime the component's query changes. This prop is handy in cases where you want to generate a side-effect whenever the component's query would change.
- 
index String[optional] The index prop can be used to explicitly specify an index to query against for this component. It is suitable for use-cases where you want to fetch results from more than one index in a single ReactiveSearch API request. The default value for the index is set to theappprop defined in the ReactiveBase component.Note: This only works when enableAppbaseprop is set to true inReactiveBase.