Using a modal to display Elastic Search-UI results, but there is a weird lag where only part of the original search term is searched

I have implemented Elastic's Search-UI on my website, where the user can enter their search term on the parent page and when they submit their search the results show up in a modal. The modal displays the search results and also has another search box the user can search again in (Search results from modal search box are displayed in modal too). This is implemented in React, I will share the source code below.

My bug:
When the user enters their search on the parent page there is this weird lag issue I cannot figure out how to fix where say the search term is "computer science", if this is typed quickly or copied into the search box only part of the search term is searched like "computer sc" which is not going to work for this site. I have added a 900ms timeout before the modal opens that "fixes" this, but it doesnt work every time and shouldn't be necessary. I will note that the search in the modal does NOT have this issue at all, there is no lag and the search works perfectly. Both searches were implemented very similarly as you can see in the code below and I have tried everything I can think of to try and fix the parent page search but no luck.

I have even added console log statements to validate that the search term used is fully captured in the search box and sent to the modal, they are both captured correctly, and yet only part of the search term is searched when the modal opens.

I am thinking there is a weird lag with the modal, but it is React's own modal implementation so I am starting to run out of ideas.

If anyone has any ideas please let me know, this is the only bug with this implementation but it is big enough that we cant put it out in prod with this type of behavior, thank you in advance

Screenshots showing the issue:

With no 900ms timeout, and the search term is copied, none of the search term shows up in the modal:

Source Code:

App.js (Parent page that opens modal)

import React, { useState } from "react";

import Modal from "./Components/Modal/Modal";
import "./App.css";
import { config } from "./config";
import {
  ErrorBoundary,
  SearchProvider,
  SearchBox,
} from "@elastic/react-search-ui";
import { closeModal } from "./Utils/utils.js";

/**
 *  Contains logic to perform a search and open the search results modal
 * @returns JSX for page
 */
export default function App() {
  const [modalOpenState, setModalState] = useState(false);
  const [inputText, setInputText] = useState("");

  return (
    <div>
      <div>
        <SearchProvider config={config}>
          <ErrorBoundary>
            <SearchBox
              inputProps={{ placeholder: "Search this site" }}
              onSubmit={(searchTerm) => {
                {
                  /* setTimeout(() => {
                 setModalState(true);
              }, 850); */
                }
                console.log(`searchTerm in App: ${searchTerm}`);
                setModalState(true);
                setInputText(searchTerm);
              }}
              searchAsYouType={true}
              autocompleteSuggestions={false}
              autocompleteMinimumCharacters={3}
              debounceLength={0}
              defaultQuery={inputText}
              autocompleteResults={{
                sectionTitle: "Results",
                titleField: "title",
                urlField: "url",
                shouldTrackClickThrough: true,
                clickThroughTags: ["test"],
              }}
            />
          </ErrorBoundary>
        </SearchProvider>
      </div>
      {/* Opens modal based on state */}
      
      {modalOpenState && (
        <Modal
          showModal={setModalState}
          open={setModalState}
          close={() => {
            setModalState(false);
            closeModal();
          }}
          
          inputText={inputText}
        />
      )}
    </div>
  );
}

Modal.js

import React from "react";
import ReactDOM from "react-dom";
import "./Modal.css";
import {
  updateAnchorTagsToOpenInParent,
  useLockBodyScroll,
  useEscapeKey,
} from "../../Utils/utils.js";
import {
  ErrorBoundary,
  SearchProvider,
  SearchBox,
  Results,
  PagingInfo,
  ResultsPerPage,
  Paging,
  WithSearch,
} from "@elastic/react-search-ui";
import { Layout } from "@elastic/react-search-ui-views";
import "@elastic/react-search-ui-views/lib/styles/styles.css";

import { config } from "../../config";

import FocusLock from "react-focus-lock";

/**
 * Displays results from SUI search on a page within modal
 * @param {*} showModal Sets state for showing modal
 * @param {*} searchResultsURL The URL for the page opened in modal
 * @returns JSX for modal
 */
export default function Modal({ open, close, inputText }) {
  console.log(`searchTerm in Modal: ${inputText}`);
  React.useEffect(() => {
    // Update anchor tags to open in parent window
    updateAnchorTagsToOpenInParent();
  }, []);

  // Call hook to lock body scroll when modal is opened
  useLockBodyScroll();

  // Escape key logic
  const sendNo = () => showModal(false);

  useEscapeKey(sendNo);

  // Return null if modalState open is false
  if (!open) return null;

  return ReactDOM.createPortal(
    <>
      <div
        className="modalBackground"
        onClick={() => {
          // close modal when outside of modal is clicked
          close();
        }}
      />
      <div className="modalContainer">
        <FocusLock>
          <SearchProvider config={config}>
            <WithSearch
              mapContextToProps={({ wasSearched, searchTerm }) => {
                console.log(`searchTerm in WithSearch: ${inputText}`); // Add this line
                return { wasSearched };
              }}
            >
              {({ wasSearched }) => {
                return (
                  <div className="App">
                    <ErrorBoundary>
                      <Layout
                        header={
                          <SearchBox
                            inputProps={{ placeholder: "Search this site" }}
                            id="modalSearchBox"
                            autocompleteMinimumCharacters={3}
                            searchAsYouType={true}
                            autocompleteResults={{
                              sectionTitle: "Results",
                              titleField: "title",
                              urlField: "url",
                              shouldTrackClickThrough: true,
                              clickThroughTags: ["test"],
                            }}
                            autocompleteSuggestions={false}
                            debounceLength={0}
                            defaultQuery={inputText}
                          />
                        }
                        bodyContent={
                          <Results
                            titleField="title"
                            urlField="url"
                            shouldTrackClickThrough={true}
                          />
                        }
                        bodyHeader={
                          <React.Fragment>
                            {wasSearched && <PagingInfo />}
                            {wasSearched && <ResultsPerPage />}
                          </React.Fragment>
                        }
                        bodyFooter={<Paging />}
                      />
                    </ErrorBoundary>
                  </div>
                );
              }}
            </WithSearch>
          </SearchProvider>
        </FocusLock>
        <div>
          <button
            type="button"
            className="closeButton"
            data-dismiss="modal"
            aria-label="Close"
            onClick={close}
          >
            X
          </button>
        </div>
      </div>
    </>,
    document.getElementById("portal")
  );
}

Thank you again in advance!!!

This got solved by my amazing co-worker!

We had to add additional props to the WithSearch component for setSearchTerm in both App.js and Modal.js, as well as resultSearchTerm in Modal.js

Here is a link to the documentation that breaks down these values, State | Elastic docs, ultimately it was a lot of trial and error, but we were able to solve it and now the search works perfectly, no timeouts, and the full search term is always captured

Props again to my amazing teammate for figuring this out!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.