The Storepoint locator drops into a React or Next.js app as a single component. Mount it on render, tear it down on unmount. The same pattern handles route changes, modals, conditional rendering, and React StrictMode.
Start with our Quick Start Guide to create your account, add locations, and configure your map. Then come back here to integrate with React.
Before You Start
You'll need:
- A Storepoint account with at least one location added
- Your Widget ID from the dashboard
- A React project (Vite, Create React App, Next.js, etc.)
Your widget ID is a short alphanumeric string (e.g. abc123). Grab it from your Embed settings.
Step 1: Add the Hook
Save this file once. It loads the widget script on first use, mounts the widget when a component renders, and tears it down on unmount.
// useStorepointWidget.js
import { useEffect, useState } from 'react';
let scriptPromise;
function loadStorepoint() {
if (window.StorepointWidget) return Promise.resolve();
if (scriptPromise) return scriptPromise;
scriptPromise = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://widget.storepoint.co/embed.js';
script.async = true;
script.onload = () => resolve();
script.onerror = reject;
document.head.appendChild(script);
});
return scriptPromise;
}
export default function useStorepointWidget(widgetId, containerRef, options) {
const [widget, setWidget] = useState(null);
useEffect(() => {
let instance;
let cancelled = false;
loadStorepoint().then(() => {
if (cancelled || !containerRef.current) return;
instance = new window.StorepointWidget(widgetId, containerRef.current, options);
instance.load();
setWidget(instance);
});
return () => {
cancelled = true;
setWidget(null);
instance?.destroy();
};
}, [widgetId]);
return widget;
}
Step 2: Render the Locator
import { useRef } from 'react';
import useStorepointWidget from './useStorepointWidget';
export default function StoreLocator() {
const containerRef = useRef(null);
useStorepointWidget('YOUR_WIDGET_ID', containerRef);
return <div ref={containerRef} style={{ width: '100%', minHeight: '500px' }} />;
}
That's the whole component. The hook handles script loading, mounting, and cleanup for you.
Next.js
The same component works in Next.js. Add 'use client' at the top so the file runs in the browser:
'use client';
import { useRef } from 'react';
import useStorepointWidget from './useStorepointWidget';
export default function StoreLocator() {
const containerRef = useRef(null);
useStorepointWidget('YOUR_WIDGET_ID', containerRef);
return <div ref={containerRef} style={{ width: '100%', minHeight: '500px' }} />;
}
SSR renders the empty container on the server. The widget mounts on the client. No extra setup, no dynamic imports.
Listening for Events
The hook returns the widget instance once it's ready. Use it in a follow-up useEffect to listen for searches, clicks, and other events:
import { useEffect, useRef } from 'react';
import useStorepointWidget from './useStorepointWidget';
export default function StoreLocator() {
const containerRef = useRef(null);
const widget = useStorepointWidget('YOUR_WIDGET_ID', containerRef);
useEffect(() => {
if (!widget) return;
widget.on('search', (data) => {
console.log('User searched:', data.query);
});
widget.on('location-result-item-click', (data) => {
console.log('Location clicked:', data.name);
});
}, [widget]);
return <div ref={containerRef} style={{ width: '100%', minHeight: '500px' }} />;
}
Listeners are removed automatically when the component unmounts.
Holding a reference to the widget instance lets you add listeners that clean up with the component, call methods like setFilters(), and remount safely on route changes. See the JavaScript API reference for everything the instance can do.
Having Trouble?
If you run into any issues, contact us and we'll help get it sorted. Please include details about your React setup and any error messages.
Next Steps
- Set up filters and tags to help customers find specific location types
- Explore embed code options for pre-filtered locators
- JavaScript API documentation for advanced integrations