Docs / Getting Started / Embed on Your Website / Add a Store Locator to React & Next.js

Add a Store Locator to React & Next.js

Drop a Storepoint store locator into any React or Next.js component with a single hook.

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.

New to Storepoint

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.)
Find Your Widget ID

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.

About the widget instance

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

Still have questions?

We're happy to help anytime.

Get in Touch

Ready to get started?

Create your locator in minutes.