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:
- 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
}}
>
- 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.
- 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));
}
- 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:
- 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
}}
>
- 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.