1Kurulum
REST istekleri için ek paket gerekmez — fetch veya axios kullanabilirsiniz. WebSocket için socket.io-client kurun:
npm install socket.io-client
API key almak için ücretsiz hesap oluşturun.
2useAltinapiPrice — Custom Hook
WebSocket bağlantısını kapsayan özel bir React hook. Bağlantı yönetimi, cleanup ve state güncellemelerini otomatik olarak halleder:
hooks/useAltinapiPrice.ts
import { useEffect, useState, useRef } from "react"; import { io, Socket } from "socket.io-client"; interface Price { symbol: string; bid: number; ask: number; ts: number; } export function useAltinapiPrice(symbols: string[], apiKey: string) { const [prices, setPrices] = useState<Record<string, Price>>({}); const [connected, setConnected] = useState(false); const socketRef = useRef<Socket | null>(null); useEffect(() => { const socket = io("https://altinapi.com", { auth: { apiKey }, transports: ["websocket", "polling"], }); socketRef.current = socket; socket.on("connect", () => { setConnected(true); socket.emit("subscribe", symbols); }); socket.on("prices:snapshot", ({ data }: { data: Price[] }) => { setPrices(prev => { const next = { ...prev }; data.forEach(p => { next[p.symbol] = p; }); return next; }); }); socket.on("prices:update", ({ data }: { data: Price[] }) => { setPrices(prev => { const next = { ...prev }; data.forEach(p => { next[p.symbol] = p; }); return next; }); }); socket.on("disconnect", () => setConnected(false)); return () => { socket.disconnect(); }; }, [apiKey, symbols.join(",")]); return { prices, connected }; }
3GoldPriceCard — Bileşen
Hook'u kullanan hazır bir fiyat kartı bileşeni:
components/GoldPriceCard.tsx
import { useAltinapiPrice } from "../hooks/useAltinapiPrice"; const SYMBOLS = ["ALTIN", "CEYREK_YENI", "USDTRY", "EURTRY"]; const LABELS: Record<string, string> = { ALTIN: "Has Altın", CEYREK_YENI: "Çeyrek Altın", USDTRY: "USD/TRY", EURTRY: "EUR/TRY", }; export function GoldPriceCard() { const { prices, connected } = useAltinapiPrice( SYMBOLS, process.env.NEXT_PUBLIC_ALTINAPI_KEY! ); return ( <div className="price-card"> <div className="price-card-header"> <h2>Canlı Fiyatlar</h2> <span className={connected ? "dot green" : "dot red"}> {connected ? "● Canlı" : "○ Bağlanıyor..."} </span> </div> <table> <thead> <tr><th>Sembol</th><th>Alış</th><th>Satış</th></tr> </thead> <tbody> {SYMBOLS.map(sym => { const p = prices[sym]; return ( <tr key={sym}> <td>{LABELS[sym]}</td> <td>{p ? p.bid.toLocaleString("tr-TR") : "—"}</td> <td>{p ? p.ask.toLocaleString("tr-TR") : "—"}</td> </tr> ); })} </tbody> </table> </div> ); }
4REST API (fetch)
WebSocket gerektirmeyen sayfalar için fetch ile anlık fiyat çekme:
React — fetch ile REST
import { useEffect, useState } from "react"; function useGoldPrice(symbol: string) { const [data, setData] = useState<any>(null); useEffect(() => { let active = true; const fetchPrice = async () => { const res = await fetch(`/api/gold/${symbol}`); // kendi proxy endpoint'iniz if (active) setData(await res.json()); }; fetchPrice(); const timer = setInterval(fetchPrice, 30_000); // 30 sn'de bir yenile return () => { active = false; clearInterval(timer); }; }, [symbol]); return data; } // Kullanım export function GoldBadge() { const price = useGoldPrice("ALTIN"); if (!price) return <span>Yükleniyor...</span>; return <span>Has Altın: {price.bid.toLocaleString("tr-TR")} TL</span>; }
5Next.js — API Route + Server Component
API key'i client'a göndermemek için Next.js API route üzerinden proxy kullanın:
app/api/gold/[symbol]/route.ts
import { NextRequest, NextResponse } from "next/server"; export async function GET( _req: NextRequest, { params }: { params: { symbol: string } } ) { const res = await fetch( `https://altinapi.com/api/prices/${params.symbol}`, { headers: { "x-api-key": process.env.ALTINAPI_KEY! }, next: { revalidate: 10 }, // 10 sn ISR cache } ); if (!res.ok) return NextResponse.json({ error: "Hata" }, { status: 502 }); const data = await res.json(); return NextResponse.json(data, { headers: { "Cache-Control": "s-maxage=10, stale-while-revalidate=59" }, }); }