Documentation
Troubleshooting and FAQs
Client Side Rendering

Client Side Rendering

Basic Setup

1. How do I configure the CSR wrapper for my React app?

The CSR Wrapper is the main component that manages the search functionality. It is recommended to render this component at the root of your application. The setWebUrl callback function can be used for routing the application to the desired page.

Default value:

const setWebUrl = (newUrl, redirect = false, replace = false) => {
	if (replace) {
		window.history.replaceState(null, "", newUrl);
	} else {
		window.history.pushState({}, "", newUrl);
	}
};

For example, you might have multiple pages with a search bar, and when entering a query, the user should be redirected to the search results page. In such cases, it is good practice to wrap all these pages with the CSR Wrapper.

2. What are the required vs optional props for CSRWrapper?

The wrapper component requires only the apiKey and siteKey to render the search functionality at the very least. The other props are optional and can be used to configure the search functionality according to your use case.

Required props:

  • apiKey & siteKey: Minimal requirements to render the search functionality.

Optional props:

  • defaultValues: Default values for the search state when nothing is present in the URL.
  • webUrlConfig: Configurations for the URL present in the web browser.
  • apiUrlConfig: Configurations for the Search API.
  • onEvent: Callback function to handle events triggered by the SDK.
<UnbxdSearchCSRWrapper
    // Required
    apiKey="your-api-key"
    siteKey="your-site-key"
 
    // Optional - Default search state
    defaultValues={{ ... }}
 
    // Optional - URL configuration
    webUrlConfig={{ ... }}
 
    // Optional - Configurations related to Search API
    apiUrlConfig={{ ... }}
 
    // Optional - onEvent function
    onEvent={(event, message, value, state) => {
        console.log("Event triggered:", event);
    }}
>

3. Why is my search not working on the first page load?

There are several possible reasons for this:

  1. Missing default query (if query is not added to URL):

You might have decided not to keep any query parameters in the URL. In such cases, the SDK will not have a default query to show results. To fix this, you can use the defaultValues prop to set the default query.

// ❌ Wrong - no default query
<UnbxdSearchCSRWrapper
	apiKey="..."
	siteKey="..."
	// Missing defaultValues
>
 
// âś… Correct - with default query
<UnbxdSearchCSRWrapper
	apiKey="..."
	siteKey="..."
	defaultValues={{
		query: "red dresses"  // Essential for initial load
	}}
>
  1. siteKey and apiKey issues:

The siteKey and apiKey are required to render the search functionality. If you are not passing the siteKey and apiKey, or if you are passing incorrect values, the SDK will not be able to render the search functionality.

  1. CORS configuration:

To use the Search SDK and get results from the search API, your domain must be whitelisted. If the domain is not whitelisted, the SDK will not be able to render the search functionality.

// Check if your domain is whitelisted
function checkCORS() {
	fetch("https://search.unbxd.io/fb853e3332f2645fac9d71dc63e09ec1/demo-unbxd700181503576558/search?q=*")
		.then((response) => console.log("CORS OK"))
		.catch((error) => console.log("CORS Error:", error));
}
  1. Wrapper placement:

The wrapper component must be rendered in such a way that all components related to the search functionality are rendered inside the wrapper. If any components are rendered outside the wrapper, the SDK will not be able to render the search functionality.

// ❌ Wrong - components outside wrapper
function App() {
	return (
		<div>
			<SearchBox /> {/* This won't work */}
			<UnbxdSearchCSRWrapper>
				<Products />
			</UnbxdSearchCSRWrapper>
		</div>
	);
}
 
// âś… Correct - all components inside wrapper
function App() {
	return (
		<UnbxdSearchCSRWrapper>
			<SearchBox />
			<Products />
		</UnbxdSearchCSRWrapper>
	);
}

State Management

1. How do I access the search state outside of the wrapper?

You cannot access the search state outside of the wrapper directly. You can only access the search state inside the wrapper by using the hooks provided by the React Search SDK.

2. I do not want to use the ready-to-use components. How do I access search state outside of components?

You can fetch any search data by making use of the hooks provided by the React Search SDK as long as it is being rendered inside the wrapper.

import { useQuery } from "@unbxd-ui/react-search-hooks";
 
const PageSummary = () => {
	const { query } = useQuery();
 
	return <div className="page-summary">You are currently searching for {query}</div>;
};

3. Can I control which components re-render on state changes?

If you want to avoid unnecessary re-renders, you can modularise the components. This makes sure that when a value returned by the hooks is being used, only that component re-renders, and not the entire application. And in cases where you are passing the hook-returned values to other components as props, you can make use of the React.memo function to prevent unnecessary re-renders.

4. How do I programmatically trigger searches?

To trigger a search API call, the user can make use of the useQuery or useCategory hook as per the use case. In case of the useQuery hook, the user can make use of the setQuery function to set the query, and in case of the useCategory hook, the user can make use of the setCategory function to set the category.

// useQuery hook
import { useQuery } from "@unbxd-ui/react-search-hooks";
 
const { setQuery } = useQuery();
setQuery("dresses");
// useCategory hook
import { useCategory } from "@unbxd-ui/react-search-hooks";
 
const { setCategory } = useCategory();
setCategory("categoryPath:'Dresses'");

Loading and Performance

1. How do I handle loading states during initial data fetch?

The useProducts hook returns both the loading state and the products. The loading state is a boolean value that is true while the products are being fetched and false when the products have been fetched.

import { useProducts } from "@unbxd-ui/react-search-hooks";
 
function ProductSkeleton() {
	// classnames which have animation can be used to show the loading state
	return (
		<div className="product-skeleton">
			<div className="skeleton-image"></div>
			<div className="skeleton-title"></div>
			<div className="skeleton-price"></div>
		</div>
	);
}
 
function CustomProductsWithLoading() {
	const { products, loading } = useProducts();
 
	if (loading) {
		return (
			<div className="products-grid">
				{Array.from({ length: 8 }).map((_, index) => (
					<ProductSkeleton key={index} />
				))}
			</div>
		);
	}
 
	return (
		<div className="products-grid">
			{products.map((product) => (
				<ProductCard key={product.id} product={product} />
			))}
		</div>
	);
}
 
function SearchPageWithLoader() {
	return (
		<UnbxdSearchCSRWrapper>
			<SearchBox />
			<CustomProductsWithLoading />
		</UnbxdSearchCSRWrapper>
	);
}

The Pagination components takes a LoaderComponent which renders a component when the search API call is in progress. We have given a set of examples for the LoaderComponent here (opens in a new tab).

2. Can I use multiple CSR wrappers on the same page?

It is recommended to use only one CSR wrapper and place it at the root of the application.

If required, you can use multiple CSR wrappers by passing the respective props to each of the wrappers. You need to make sure that URL changes made by one wrapper does not affect the other wrapper.

In case you have multiple wrappers, the rendered results will interact with the nearest parent wrapper.

URL Management and Persistence

1. How do I persist search state across page refreshes?

The React Search SDK makes use of the URL to create and maintain the search state across page refreshes. The webUrlConfig prop is essential to make use of the URL. In cases where nothing is added to the URL, the user can make use of the defaultValues prop to set the default values for the search state.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	webUrlConfig={{
		query: { addToUrl: true },
		facets: { addToUrl: true },
		sort: { addToUrl: true },
		currentPage: { addToUrl: true },
		pageSize: { addToUrl: true },
		view: { addToUrl: true },
	}}
	defaultValues={{
		query: "dresses",
		pageSize: 20,
		currentPage: 1,
		sort: "date desc",
		view: "grid",
	}}>
	...
</UnbxdSearchCSRWrapper>

2. Why do my filters reset when navigating back?

According to the default implementation of the React Search SDK, the URL is added to the history stack only on initial load. After that, any user interaction that changes the URL is not added to the history stack. Instead, it replaces the existing URL. However, this implementation can be changed by using the setWebUrl callback function.

3. What is the setWebUrl function? What value must I pass to it?

The setWebUrl function is a configurable URL management function that handles how URL changes are reflected in the browser's history. It's part of the webUrlConfig configuration.

This is the default value:

const setWebUrl = (newUrl, redirect = false, replace = false) => {
	if (replace) {
		window.history.replaceState(null, "", newUrl);
	} else {
		window.history.pushState({}, "", newUrl);
	}
};
  • newUrl is the URL to be set.
  • redirect is a boolean value to indicate if the user should be redirected to the new URL.
  • replace is a boolean value to indicate if the new URL should replace the current URL in the history stack.

Here are some examples of values that can be passed to the setWebUrl function in different frameworks:

React:

import { useNavigate } from "react-router-dom";
 
const navigate = useNavigate();
 
setWebUrl: (newUrl, redirect = false, replace = false) => {
	if (redirect) {
		window.location.href = newUrl;
	} else if (replace) {
		navigate(newUrl, { replace });
	} else {
		navigate(newUrl);
	}
};

4. Can I customise the URL? If yes, how do I do it?

Yes, you can customise the URL by making use of the webUrlConfig prop. The React Search SDK gives you the option to have custom parameter names and values, customise the order of parameters in the URL, and also hide the parameters to the URL.

You can choose to show, hide or replace values for the following parameters:

  • query: Search query configuration
  • imageQuery: Image search configuration
  • category: Category navigation
  • sort: Sorting parameters
  • view: View type (grid/list)
  • pageSize: Results per page
  • pagination: Page navigation

For more details and more configurations, you can refer to this (opens in a new tab) documentation on webUrlConfig.

5. Can I add extra parameters to the URL?

Yes, you can add extra parameters to the URL by making use of the externalParams prop.

There are three use cases:

  1. Passing null value:

This will keep all the parameters in the URL.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	webUrlConfig={{
		externalParams: null // keeps all the parameters in the URL
	}}
>
 
2. Passing an array of parameters:
 
This will keep only the parameters passed in the array in the URL. If there are other parameters that are present in the URL, they will be removed from the URL. This ensures that the URL is not cluttered with unnecessary parameters.
 
```js
<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	webUrlConfig={{
		externalParams: ["ref"] // keeps the 'ref' parameter in the URL
	}}
>
  1. Passing an empty array:

This will remove all the parameters from the URL.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	webUrlConfig={{
		externalParams: [] // removes all the parameters from the URL
	}}
>

Event Handling and Monitoring

1. What is the onEvent function?

The onEvent function is a callback function that helps you track and handle various events that occur during the search functionality. It's a powerful tool for monitoring user interactions, handling errors, and implementing custom behaviors. Here (opens in a new tab) is the list of events supported by the React Search SDK.

This is the default value:

const onEvent = ({ type, message, value, state }) => {
	if (message) {
		console.log(`${type}:`, message, value);
	} else {
		console.log(type);
	}
};
  • type: The type of event.
  • message: A descriptive message about the event.
  • value: The value associated with the event.
  • state: Current search state.

This function is particularly useful for:

  • Debugging and monitoring
  • User feedback (showing loading states, success/error messages)
  • Analytics tracking
  • Custom behavior implementation based on search events
  • Error handling and logging
  • Performance monitoring

API Configuration

1. The end point for the search API is different from the default one. How do I change it?

The default endpoint for the search API is "https://search.unbxd.io". This can be configured using the searchEndPoint property of the apiUrlConfig prop.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	apiUrlConfig={{
		searchEndPoint: "https://search.unbxd.io",
	}}
>

2. The parameter in the API URL for browse functionality is different from the default one. How do I change it?

The default browse query parameter in the search API is "p". This can be configured using the category property of the apiUrlConfig prop.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	apiUrlConfig={{
		category: {
			browseQueryParam: "p",
		}
	}}
>

3. I want to add more params to the search API call. How do I do this?

The extraParams property of the apiUrlConfig prop is used to add additional parameters to the search API call.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	apiUrlConfig={{
		extraParams: {
			stats: "price",
		}
	}}
>

4. How do I add headers to the search API call?

The headers property of the apiUrlConfig prop allows you to add custom headers to the search API call.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	apiUrlConfig={{
		headers: {
			"unbxd-user-id": "your-user-id",
		}
	}}
>

Filters and Categories

1. I am able to add the range filter or/and category filter, but on reloading the page, they get removed. How do I fix this?

The Search API response contains filters of three types: "text", "range", and "multilevel" (category), and each type is processed differently. Since the response varies from customer to customer, the SDK needs to know the names of range and category filters.

The apiUrlConfig prop is used to configure the Search API. The rangeFacets and categoryFacets properties are used to configure the range and category filters.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	webUrlConfig={{
		rangeFacets: ["price"],
		categoryFacets: ["categoryPath"],
	}}
>

Product Display and Variants

1. I want to display some information in the product card, but I do not get this info in the 'product' object passed to the ProductComponent in the Products component. How do I fix this?

The search API requires an array of fields to be fetched for each product. The products property of the apiUrlConfig prop is used to configure which fields should be fetched for each product.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	apiUrlConfig={{
		products: {
			fields: ["title", "price", "imageUrl", "uniqueId", "productUrl"],
		}
	}}
>

2. I want to display the variants of each product. But I do not get the variants in the 'product' object passed to the ProductComponent in the Products component. How do I fix this?

By default, the search API does not provide the variants of each product. However, you can use the variants property of the apiUrlConfig prop to configure the variants.

<UnbxdSearchCSRWrapper
	apiKey="your-api-key"
	siteKey="your-site-key"
	apiUrlConfig={{
		variants: {
			enabled: true,
			attributes: ["title", "v_imageUrl"],
			count: 5,
		}
	}}
>

After enabling the variants, you will receive the variants in the "product" object passed to the ProductComponent in the Products component.