React
Kompatibilitet
Sektion kaldt “Kompatibilitet”SDK’et er et browserbibliotek. Det afhænger af window, document, navigator og localStorage, og renderer direkte ind i DOM-elementet med det id, du angiver. Det fungerer i enhver React-app, der kører i browseren (Vite, CRA, Next.js, Remix m.fl.).
I SSR-frameworks (Next.js App Router, Remix) skal SDK’et kun instantieres på klienten — inde i useEffect eller fra en 'use client'-komponent.
Installation
Sektion kaldt “Installation”npm install @magicfeedback/nativeImportér stylesheettet én gang i din apps entry:
// fx main.tsx, _app.tsx, layout.tsximport "@magicfeedback/native/dist/styles/magicfeedback-default.css";Basis-komponent
Sektion kaldt “Basis-komponent”Minimal mønster: en container <div> med et stabilt id og en useEffect, der kalder init og generate én gang.
import { useEffect } from "react";import magicfeedback from "@magicfeedback/native";
export function FeedbackSurvey() { useEffect(() => { magicfeedback.init({ env: "prod" });
const form = magicfeedback.form("APP_ID", "PUBLIC_KEY"); form.generate("survey-root", { addButton: true, addSuccessScreen: true, }); }, []);
return <div id="survey-root" />;}Genbrugelig hook
Sektion kaldt “Genbrugelig hook”Skal du mounte undersøgelsen flere steder, så pak opsætningen ind i en hook:
import { useEffect } from "react";import magicfeedback from "@magicfeedback/native";import type { generateFormOptions } from "@magicfeedback/native/dist/types/src/models/types";
export function useMagicFeedbackForm( containerId: string, appId: string, publicKey: string, options?: generateFormOptions,) { useEffect(() => { magicfeedback.init({ env: "prod" }); const form = magicfeedback.form(appId, publicKey); form.generate(containerId, options); }, [containerId, appId, publicKey]);}function FeedbackPage() { useMagicFeedbackForm("survey-root", "APP_ID", "PUBLIC_KEY", { addButton: true, questionFormat: "slim", });
return <div id="survey-root" />;}Next.js (App Router)
Sektion kaldt “Next.js (App Router)”"use client";
import { useEffect } from "react";import magicfeedback from "@magicfeedback/native";import "@magicfeedback/native/dist/styles/magicfeedback-default.css";
export function FeedbackSurvey() { useEffect(() => { magicfeedback.init({ env: "prod" }); const form = magicfeedback.form( process.env.NEXT_PUBLIC_MF_APP_ID!, process.env.NEXT_PUBLIC_MF_PUBLIC_KEY!, ); form.generate("survey-root", { addButton: true }); }, []);
return <div id="survey-root" />;}Render i en modal
Sektion kaldt “Render i en modal”SDK’et tegner ikke modalen — det gør dit designsystem. Mount undersøgelsen først, når modalen åbnes.
import { useEffect } from "react";import magicfeedback from "@magicfeedback/native";
export function FeedbackModal({ open, onClose,}: { open: boolean; onClose: () => void;}) { useEffect(() => { if (!open) return;
const form = magicfeedback.form("APP_ID", "PUBLIC_KEY"); form.generate("survey-root", { addButton: true, addSuccessScreen: true, questionFormat: "slim", afterSubmitEvent: ({ completed }) => { if (completed) onClose(); }, }); }, [open]);
if (!open) return null;
return ( <Dialog onClose={onClose}> <div id="survey-root" /> </Dialog> );}Se Rendering surfaces for flere mønstre (drawer, bottom sheet, dedikeret side).
Livscyklus-events
Sektion kaldt “Livscyklus-events”useEffect(() => { const form = magicfeedback.form("APP_ID", "PUBLIC_KEY"); form.generate("survey-root", { onLoadedEvent: () => analytics.track("survey_loaded"), afterSubmitEvent: ({ completed }) => { if (completed) analytics.track("survey_completed"); }, });}, []);Se Livscyklus-events for hele overfladen.