Few filtering and redirect issues

I have a few questions about the instantsearch with react router 4.

  1. how do i use the searchbox in my header instead of using the one on the same page as the results.
  2. the line onSearchStateChange={this.onSearchStateChange.bind(this)} which works with the searchbox, also has the effect that when navigating away from the results page it will after a few seconds, redirect me back to the results page, how do i stop this?
  3. the hitsPerPage doesnt change anything, even at 1 it returns more then the amount specified.

my code is as follows:

import React, { Component, PropTypes } from 'react';
import {
  InstantSearch,
  HierarchicalMenu,
  Hits,
  Menu,
  Pagination,
  StarRating,
  RefinementList,
  SearchBox,
  ClearAll,
} from 'react-instantsearch/dom';
import { Grid, Row, Col, Image } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import qs from 'qs';

const updateAfter = 700;

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

const searchStateToUrl = (props, searchState) =>
  searchState ? `${props.location.pathname}${createURL(searchState)}` : '';

class Algolia extends Component {
  constructor(props) {
    super(props);
    this.state = { searchState: qs.parse(props.location.search.slice(1)) };
  }

  onSearchStateChange = searchState => {
    clearTimeout(this.debouncedSetState);
    this.debouncedSetState = setTimeout(
      () => {
        this.props.history.push(
          searchStateToUrl(this.props, searchState),
          searchState
        );
      },
      updateAfter
    );
    this.setState({ searchState });
  };

  render() {
    return (
      <InstantSearch
        appId="somerandomid"
        apiKey="somerandomkey"
        indexName="somerandomname"
        hitsPerPage="1"
        searchState={this.state.searchState}
        onSearchStateChange={this.onSearchStateChange.bind(this)}
        createURL={createURL}
      >

        <Grid>
          <Row>
            <Col xs={2}>
              <h4>Search By</h4>
              <Menu attributeName="type" />
              <ClearAll />
            </Col>

            <Col xs={10}>
              <Hits hitComponent={Products}/>
              <Pagination showLast={true} />
            </Col>
          </Row>

        </Grid>
      </InstantSearch>
    );
  }
}

function Products({hit}) {
  var productboxes = {
    float:"left",
    marginBottom:"20px",
    height: "250px"
  };
  var images = {
    width:"100%"
  };
  return (
          <Col md={4} style={productboxes}>
            <Link to={`${hit.objectID}`}>
              <div>
                <Image src={`{hit.cover}`} alt={hit.name} responsive />
                  <Col md={12}>
                    {hit.name}
                  </Col>
                  <Col md={6}>
                    ${hit.discount_gbp}
                  </Col>
                  <Col md={6}>
                    {hit.price_gbp}
                  </Col>
                </div>
              </Link>
            </Col>
          );
        }

Algolia.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func.isRequired,
  }),
  location: PropTypes.object.isRequired,
};

export default Algolia;
1 Like

Hi @nritsonsa!

  1. If you want to have a SearchBox in a complete different component than the result page and can’t have the InstantSearch root component encapsulate them both, then you need to use two <InstantSearch> and retrieve the search state from the one with SearchBox, to give it to the second with the results. You might perform a merge because the second is also handling URL.

  2. I assume that’s because when we unmount every widgets including the InstantSearch root component then we call onSearchStateChange. We have an open issue about this react-instantsearch triggers unnecessary requests when everything is unmounted · Issue #2061 · algolia/instantsearch · GitHub and the fix should remove this behaviour. In the mean time, could you tell me if having a state set to true when clicking on a results and then if this state is true don’t update the URL would work?

  3. To configure the hitsPerPage search parameters, you need to use the <Configure> widget.

1 Like

Hello old thread!

I’m also interesting in trying to retrieve the search state to use in a separate instance of <InstantSearch>, but I think the documentation has changed since that link was made, and the current redirect is to a page that does not (unless I’m just not seeing it) cover retrieving the search state.

Can you help point me to the documentation on this?

HI @alex.fornuto,

The guide has moved but it’s almost the same content. The part of the guide that refers to the retrieval of the searchState is the first snippet of Basic URL. Here we retrieve the state from the URL.

const urlToSearchState = ({ search }) => qs.parse(search.slice(1));

Hope that helps!

Thanks @samuel.vaillant - sorry to have a discussion spanning two threads here. I think what I’m asking is how to have two instances of <InstantSearch>, one with a searchbox, and another (in another file) which has a result box that uses the results from the first component.

Yes I understood your requirement and the URL would be the solution to share the state between those two instances. The first instance in the Header will write to the URL, then the results page can read its initial state from the URL to display the expected results. In that case two search requests will hit Algolia one per instance. As mentioned in the other thread you can leverage a single client to mitigate this issue.

Newbie React Component Questions - #3 by samuel.vaillant

I see! Sorry, I didn’t realize that we were talking about writing to the URL as well as reading from it. I’ll dive into the linked documentation, both from Algolia and Gatsby’s wrapRootElement stuff, though the latter may be a bit over my head (As often happens when a tech writer needs to be his own dev).

Thanks!