Display instant products (Shopify Hydrogen)

This is for:

Developer

Instant products enhance the search experience by displaying relevant products in real time as users type in the search box.

Instant results with Headless in Shopify | Coveo for Commerce

To display instant products, you can use the InstantProducts controller.

To implement, first, define the controller:

    instantProducts: defineInstantProducts(), 1
1 The instantProducts controller displays relevant products in real time as users type in the search box.

Next, incorporate the controller into your existing search box component to seamlessly integrate instant product features into the search experience.

// app/components/StandaloneSearchBoxWithInstantProducts.tsx

import {useNavigate} from '@remix-run/react';
import {useEffect, useRef} from 'react';
import {
  useInstantProducts,
  useStandaloneSearchBox,
} from '~/lib/commerce-engine';

function useUpdateInstantProducts(
 1
  searchBox: ReturnType<typeof useStandaloneSearchBox>,
  instantProducts: ReturnType<typeof useInstantProducts>
) {
  useEffect(() => {
    if (searchBox.state.suggestions[0]) {
      instantProducts.methods?.updateQuery(
        searchBox.state.suggestions[0]?.rawValue
      );
    }
  }, [searchBox.state.suggestions, instantProducts.methods]);
}

export function StandaloneSearchBoxWithInstantProducts() {
  const searchBox = useStandaloneSearchBox();
  const inputRef = useRef<HTMLInputElement>(null);
  const navigate = useNavigate();
  const instantProducts = useInstantProducts(); 2
  useUpdateInstantProducts(searchBox, instantProducts); 3

  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  useEffect(() => {
    if (searchBox.state.redirectTo === '/search') {
      navigate(
        `${searchBox.state.redirectTo}?q=${encodeURIComponent(
          searchBox.state.value
        )}`
      );
    }
  }, [searchBox.state.redirectTo, searchBox.state.value, navigate]);

  const handleSuggestionClick = (suggestion: string) => {
    searchBox.methods?.updateText(suggestion);
    inputRef.current!.value = suggestion;
    searchBox.methods?.showSuggestions();
  };

  return (
    <div>
      <input
        ref={inputRef}
        aria-label="Search"
        placeholder="Search"
        onChange={(e) => searchBox.methods?.updateText(e.target.value)}
        onFocus={() => searchBox.methods?.showSuggestions()}
      />
      <button type="button" onClick={searchBox.methods?.submit}>
        Search
      </button>

      {searchBox.state.suggestions.length > 0 && (
        <div>
          {searchBox.state.suggestions.map((suggestion) => (
            <button
              type="button"
              key={suggestion.rawValue}
              onClick={() => handleSuggestionClick(suggestion.rawValue)}
            >
              {suggestion.highlightedValue}
            </button>
          ))}
        </div>
      )}

      {searchBox.state.suggestions.length > 0 &&
        instantProducts.state.products.length > 0 && ( 4
          <div>
            {instantProducts.state.products.map((product) => (
              <div key={product.ec_product_id}>
                <h2>{product.ec_name}</h2>
              </div>
            ))}
          </div>
        )}
    </div>
  );
}
Instant products annotations
1 Create a custom hook to update the InstantProducts controller state whenever the search box suggestions change. This occurs when the user types in the search box.
2 Use the useInstantProducts hook to access the InstantProducts controller.
3 Use the custom hook to sync the InstantProducts controller with the search box.
4 Display the instant products by iterating through the instantProducts.state.products array.