November 1, 2026

How to Add Live Chat to a React App: Snippet, Effect and Routes

Add live chat to a React app: code editor showing a small component that loads the chat widget script

To add live chat to a React app you have two clean options: paste the Talkmio snippet into the HTML shell, or load the script from a small effect so you control when it appears. Both take minutes, neither needs a special package and both work with Vite, Create React App and other single-page setups. This guide shows each method, explains the traps that single-page apps create, such as double effects in development and chat bubbles that appear on pages where they should not, and ends with a checklist you can run before shipping.

Talkmio is an AI live chat for websites. Its assistant, Mio, answers from your own pages and documents in the visitor’s language and hands over to your team when it cannot answer. The widget is a single script, so it does not depend on your framework. The Integrations page lists React and Next.js as supported with a component, and any other setup works with the same snippet.

Before You Start: What You Need

Create a free account at app.talkmio.com, confirm your e-mail and add your website under Websites. You receive a site key and an install snippet. Keep both open, because you will paste the snippet or read the values from it. Add your public website and a few documents to the Mio knowledge base so the chat can answer real questions the moment it appears; the knowledge base screen in your account walks you through each source type.

If your app sits behind a login and has no public marketing pages, Mio has nothing public to read, so plan to add Q&A pairs, free text or uploaded files to the knowledge base instead. Mio accepts PDF, DOCX, TXT, MD, CSV and HTML files up to 15 MB each.

Add Live Chat to React App Shell: Paste the Snippet

The simplest way to add live chat to React app projects is the same as for any website: paste the snippet before the closing body tag of the HTML file your bundler serves. In a Vite project that file is index.html in the project root. In Create React App it is public/index.html. Place the snippet below the root div and the module script.

<body>
  <div id="root"></div>
  <script type="module" src="/src/main.jsx"></script>
  <!-- Talkmio snippet copied from Websites in your account -->
</body>

Because a single-page app loads the HTML once, the widget loads once and stays on screen as the visitor moves between routes. You do not need to reload it on navigation. The downside is that the widget appears on every route, including a checkout or a logged-in dashboard, and it loads in development as well as production.

Method 2: Load the Script From a React Effect

If you want control, load the script yourself. A small component adds the script element on mount and removes what it added on unmount. Read the script address and the site key from the snippet in your account; the placeholders below stand for those values.

import { useEffect } from "react";

export default function TalkmioChat() {
  useEffect(() => {
    if (import.meta.env.MODE !== "production") return;
    if (document.getElementById("talkmio-widget")) return;
    const s = document.createElement("script");
    s.id = "talkmio-widget";
    s.async = true;
    s.src = "SCRIPT_ADDRESS_FROM_YOUR_SNIPPET";
    document.body.appendChild(s);
  }, []);
  return null;
}

The id guard matters. In development React Strict Mode runs effects twice, and without the guard you would add the script two times and might get two chat bubbles. The production check keeps test traffic out of your inbox. If your snippet needs the site key as an attribute or a variable, copy it exactly as shown in your account and do not rename it. The official useEffect reference explains why effects run twice in development and when cleanup is needed.

Which Method Should You Use?

Question Paste into index.html Load from an effect
Effort Lowest: one paste One small component
Hide on some routes No, it loads everywhere Yes, render the component only where you want it
Skip in development Needs a template variable Yes, with a mode check
Wait for cookie consent Needs extra code Yes, render after consent
Risk of double loading None Low with an id guard
Best for Marketing sites and simple apps Apps with logins, consent and routes

If you are unsure, start with the paste method and move to the effect when you need a rule. A chat bubble covering a payment form is a common reason to switch.

Single-Page App Traps and How to Avoid Them

Chat on pages where it should not appear

With the effect method, render TalkmioChat inside the layout used by public pages only. Keep it out of the checkout, the admin area and any screen where the bubble overlaps controls. With the paste method, use the widget position setting under Websites to move the bubble to the left or right so it avoids your main buttons.

Route changes and page tracking

Talkmio shows your team the page a visitor is on in the live visitors list. In a single-page app the address changes without a full page load, so what your team sees depends on the widget noticing history changes. Test this: open two routes in a private window and check the Visitors page in your Talkmio account to see what appears. If something is off, write to [email protected] with the route and what you see rather than adding fragile workarounds.

Consent and cookies

If your site shows a cookie banner, decide whether the chat loads before or after consent and document the choice. With the effect method you can render the component only when consent is given. The article on chat widget cookies and consent explains the options, and the one on Google Tag Manager shows a tag-based alternative.

Server-side rendering and hydration

If you use a framework that renders on the server, a script added in an effect only runs in the browser, which is what you want. Do not add the script directly in a server-rendered component body, or it may run twice or cause a hydration warning. For Next.js apps follow our dedicated guide to adding live chat to Next.js; for Vue, see Vue and Nuxt.

Performance and Loading

A chat widget is a third-party script, and every third-party script has a cost. Load it asynchronously, as the effect above does, so it never blocks rendering. If you care about Core Web Vitals, measure before and after. The guide to live chat widget page speed shows how to test impact and how to delay loading until the browser is idle. On a single-page app the heaviest cost is usually your own bundle, not the widget, but measure rather than assume.

TypeScript, Environment Variables and Team Workflow

If your project uses TypeScript, the component above compiles as it is, because it only touches the document and does not read anything from the widget. Keep the script address and any site key in environment variables that your build injects, for example one value for production and none for development. The site key is public by nature, since it ships to every visitor’s browser, so there is no secret to hide, but keeping it in configuration means you can point staging at a separate Talkmio website and keep test conversations out of your real Inbox.

That last point is worth a few minutes. A free account lets you add one website, and paid plans allow more, so a small team can run a staging site with its own key. Agree who tests: a developer checks that the bubble loads and survives routes, while someone from support checks the welcome text, the offline message and the hand-off. Write the test in your release checklist so it is repeated every time you change layouts or routing, because a new layout wrapper is the most common way a chat bubble quietly disappears from a section of the app.

Finally, keep the loader in one place. If three different developers add the script in three components, you will eventually have a chat on every route and a second one on the home page. A single component, imported in one layout, is easier to review and easier to remove if you ever change tools.

Test the Chat Before You Ship

  1. Build the app, serve the production build and open it in a private window.
  2. Confirm exactly one chat bubble appears and that it survives route changes.
  3. Ask Mio two or three real customer questions and check that each answer comes from your own content.
  4. Send a message that needs a human, such as asking for a person, and confirm it appears in the Inbox with a notification.
  5. Open the app in development and confirm the bubble does not appear if you chose to skip it.
  6. Check the widget on a phone, including with the on-screen keyboard open.

Use Try Mio in the account to see which knowledge pieces produced each answer. Changes you make to widget colour, assistant name, welcome text or business hours under Websites apply within five minutes, so you rarely need a new deploy for content or style changes. The React documentation is a good reference if you want to structure the component differently.

When Not to Build Your Own Component

It is tempting to wrap everything in custom hooks and context providers. For a chat widget that is rarely worth it. The vendor script manages its own window, state and styling, and the more you wrap it, the more you own when it changes. Keep your code to a loader and, if needed, a consent check. Leave conversations, colours and texts to the account settings, where non-developers on your team can change them without a pull request.

Frequently Asked Questions

Do I need an npm package to add live chat to a React app?

No. The Talkmio widget is one script, so you can paste the snippet into your HTML file or load it from a small effect. The Integrations page also lists a React and Next.js component, but neither method requires installing anything in your dependencies.

Why do I see two chat bubbles in development?

React Strict Mode runs effects twice in development, so a script added without a guard loads twice. Give the script element an id and return early if it already exists. The paste method in index.html does not have this problem.

Will the chat survive route changes in my single-page app?

Yes, because the script loads once with the page shell and stays on screen as routes change. If you want the bubble only on some routes, load it from a component rendered in those layouts, and test what the live visitors list shows.

Can I hide the chat on the checkout page?

With the effect method, render the loader only inside public layouts and leave it out of checkout. With the pasted snippet, use the widget position setting to move the bubble away from important buttons, because the widget loads on every route.

Does the chat work with a Vite or Create React App project?

Yes. Both serve an HTML file where you can paste the snippet before the closing body tag, or you can load the script from a component. The widget does not depend on your bundler, framework version or router.

How much does Talkmio cost for a React site?

Nothing to start: the Free plan includes one operator, one website and 50 AI answers a month. Pro is 19 euro a month and Ultimate 49 euro a month, with a 14-day trial on paid plans. Prices are on the pricing page, with VAT added at checkout.

The Bottom Line

To add live chat to a React app, start with the simplest option: paste the snippet into your HTML shell and test it in a production build. Move to a small effect component only when you need route rules, consent or a development switch, and always guard against double loading. Keep conversation settings in the account, not in code. Start free with Talkmio, add your site and check the plans on the pricing page when you outgrow the free tier.


Try Talkmio on your site

Free plan, no card required.

Start free