Chuyển tới nội dung chính

React và Next.js (@hatang/chat-react)

@hatang/chat-react nạp widget chat Hạ Tầng trong ứng dụng React hoặc Next.js. Gói có một component không render gì, chỉ chèn script widget đúng một lần, và một hook trả về JS API $hatang đã có kiểu. Widget vẫn là widget web, cùng giao diện và cùng cài đặt trong dashboard; gói này chỉ lo phần nạp và kiểu TypeScript.

Phiên bản

@hatang/chat-react 0.1.2 · React 18+ · Next.js 14+ (App Router và Pages Router) · npm · changelog: tệp CHANGELOG.md trong gói

Trước khi bắt đầu​

  • Một kênh website trong Hạ Tầng. Chép Site ID (site_...) ở Hỗ trợ → Kênh → chọn website.
  • Tên miền ứng dụng của bạn chạy phải là tên miền của website (hoặc tên miền phụ), hoặc nằm trong Origin được phép thêm ở cài đặt website. Thêm http://localhost:3000 vào đó khi phát triển trên máy.

Cài đặt​

npm install @hatang/chat-react

Nạp widget​

Render <HatangChat /> một lần trong root layout. Module bắt đầu bằng "use client" nên dùng thẳng được trong App Router.

app/layout.tsx
import { HatangChat } from "@hatang/chat-react";

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="vi">
<body>
{children}
<HatangChat siteId="site_123..." />
</body>
</html>
);
}

Ở lần render đầu, component đặt window.HATANG_SITE_ID, đặt window.HATANG_CONFIG nếu bạn truyền config, rồi chèn https://chat.hatang.dev/widget.js với async. Script không bao giờ bị chèn hai lần, kể cả khi component render lại hay được render nhiều chỗ. Sau khi trang đầu tiên tải xong, website trong dashboard hiện trạng thái đã cài.

Props​

PropKiểuMặc địnhTác dụng
siteIdstringbắt buộcSite ID của website
hoststringhttps://chat.hatang.devNơi phục vụ widget.js. Chỉ đổi khi chạy gateway local
configHatangConfig—{ position?: "left" | "right"; locale?: "vi" | "en"; hideLauncher?: boolean }, ghi vào window.HATANG_CONFIG trước khi script tải
userHatangIdentity—{ userId?, email?, name?, phone?, hash?, data? }. Gọi identify khi widget sẵn sàng, và gọi lại mỗi khi userId, email, name hoặc hash đổi

config chỉ được đọc một lần, lúc script được chèn; đổi sau đó không tới được widget. Muốn đổi ngôn ngữ lúc chạy, gọi setLocale. Tuỳ chọn offset và mobileOffset của HATANG_CONFIG chưa có trong kiểu HatangConfig; nếu cần, tự đặt window.HATANG_CONFIG trước khi component render (xem Widget web và JS API).

Gọi widget từ code​

useHatang() (hook) và hatang() (hàm thường, dùng ngoài component) trả về cùng một object. Lệnh gọi trước khi widget tải xong được xếp hàng, nên gọi lúc nào trong trình duyệt cũng được. Ở server, các lệnh không làm gì.

"use client";
import { useHatang } from "@hatang/chat-react";

export function SupportButton() {
const chat = useHatang();
return <button onClick={() => chat.open()}>Chat với chúng tôi</button>;
}
HàmTác dụng
open(), close(), toggle()Mở, đóng hoặc bật/tắt cửa sổ chat
hide(), show()Ẩn, hiện nút chat (ví dụ trên trang thanh toán)
identify(identity)Gắn người dùng đã đăng nhập; hash tính ở server (Nhận diện khách)
setData(data)Thuộc tính tuỳ chỉnh hiển thị cho nhân viên
setLocale("vi" | "en")Đổi ngôn ngữ widget
pushEvent(name, data?)Ghi một sự kiện vào dòng thời gian của khách
on(event, cb), off(event, cb)Nghe ready, open, close, message:received, message:sent, conversation:status
reset()Quên khách hiện tại (khi đăng xuất). Widget tải lại trang để bắt đầu phiên mới
"use client";
import { useEffect } from "react";
import { hatang } from "@hatang/chat-react";

export function ChatAnalytics() {
useEffect(() => {
const chat = hatang();
const onReply = (m?: unknown) => track("chat_reply", m);
chat.on("message:received", onReply);
return () => chat.off("message:received", onReply);
}, []);
return null;
}

Widget còn nhận những lệnh mà API có kiểu này chưa liệt kê, như lead. Tự đẩy chúng vào hàng đợi: window.$hatang.push(["lead", { email, name }]). Danh sách lệnh và sự kiện đầy đủ ở Widget web và JS API.

Nhận diện người dùng đã đăng nhập​

Tính hash, tức HMAC-SHA256 của user id với identity secret của site, ở server rồi truyền xuống cùng người dùng. Đừng bao giờ đưa secret vào bundle phía client.

app/layout.tsx (Server Component)
import { createHmac } from "node:crypto";
import { HatangChat } from "@hatang/chat-react";
import { currentUser } from "@/lib/auth";

export default async function RootLayout({ children }: { children: React.ReactNode }) {
const user = await currentUser();
const identity = user
? {
userId: user.id,
email: user.email,
name: user.name,
hash: createHmac("sha256", process.env.HATANG_IDENTITY_SECRET!).update(user.id).digest("hex"),
}
: undefined;
return (
<html lang="vi">
<body>
{children}
<HatangChat siteId="site_123..." user={identity} />
</body>
</html>
);
}

Với hash hợp lệ, hộp thư đánh dấu khách là đã xác minh và gộp hội thoại với các phiên trước của cùng người, kể cả phiên trong ứng dụng di động. Gọi hatang().reset() khi người dùng đăng xuất để người tiếp theo trên cùng trình duyệt không mang danh tính cũ.

Không dùng useEffect​

Với Pages Router, framework khác hoặc template HTML thuần, hatangSnippet(siteId, host?, config?) trả về đúng đoạn script inline mà dashboard hiển thị, dưới dạng một chuỗi. Đặt nó vào thẻ <script> hoặc next/script:

import Script from "next/script";
import { hatangSnippet } from "@hatang/chat-react";

<Script id="hatang" strategy="afterInteractive">
{hatangSnippet("site_123...", undefined, { locale: "vi" })}
</Script>

Các export​

HatangChat, HatangChatProps, hatang, useHatang, HatangApi, HatangIdentity, HatangEvent, HatangConfig, hatangSnippet, inlineSnippet và widgetUrl.

Changelog​

0.1.1: trang npm mô tả widget và Hạ Tầng, dẫn tới hướng dẫn này; README có thêm phần About Ha Tang. Không đổi code.

0.1.0: bản đầu tiên. <HatangChat siteId host config user /> nạp widget một lần; useHatang() / hatang() với open, close, toggle, hide, show, identify, setData, setLocale, pushEvent, on, off và reset, được xếp hàng đến khi widget tải xong.

Bước tiếp theo​

Xem trang này dạng Markdown