holodepth

Framework entegrasyonları · React Three Fiber

useFrame / useThree: Kare Diplomasisi ve Store Gözü

Deklaratif ağaç durağanı anlatır; canlı ürün kare içinde mutasyon ister. Bu sayfa useThree ile store'dan seçici okumayı ve useFrame ile güvenli kare ticini anlatır: React render saati ile R3F kare saati karıştırılmaz.

Holodepth bu yaprağı React hooks 101 veya Three.js Clock / requestAnimationFrame teorisinin tekrarı olarak yazmaz. React varsayılır (React Vitae). Canvas frameloop mührü Canvas & kök sözleşme yaprağındadır. JSX katalog haritası Deklaratif sahne grafı yaprağındadır. Ms bütçesi / FPS SLA Platform · FPS mantığı yaprağındadır. glTF yükleme bu kapının konusu değildir.

Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «useThree seçici gözdür; gereksiz abonelik pahalıdır. useFrame kare ticine yazılır, her karede setState yazılmaz. Mutasyon ref/Object3D üzerindendir. priority sıra diplomasisidir. demand kökünde invalidate köprüsü gerekir. Sonraki kapı yükleme & Suspense köprüsüdür.»

Bu sayfanın sınırı · komşu konularla ayrım

Bu sayfa R3F'de kare / store diplomasisini anlatır:

  • Render saati vs kare saati
  • useThree seçicileri · abonelik maliyeti
  • useFrame sözleşmesi · delta / elapsed
  • ref mutasyonu · priority · invalidate köprüsü

Bilinçli olarak dışarıda bırakılan konular:

Kısa ayrım: Bu sayfa «karede kim neyi günceller?» · Canvas «metronom kökte nasıl mühürlenir?» · Deklaratif «ağaç nasıl yazılır?» · Platform FPS «ms bütçesi / jank».

İki saat: render ve kare

React render'ı durum değişince (veya üst yeniden çizilince) çalışır. R3F karesi ise Canvas metronomuna bağlıdır: always ise sürekli, demand ise geçersizkılınca. Holodepth: bu iki saati aynı cümlede karıştırmayın. UI checkbox'ı için setState; orbit / sallanma / trail için useFrame.

Imperatif Three'de kendi animate döngünüzü yazarsınız. R3F'de döngü kökte vardır; sizin işiniz o döngüye abonelik eklemektir. Aboneliği her React render'ında yeniden icat etmek değil, kare callback'inde Object3D'yi itmektir.

Render gerçeği anlatır; kare hareketi taşır.

useThree: seçici göz

useThree, Fiber store'undan gl, camera, scene, size, viewport, clock, invalidate gibi alanları okur. Holodepth kuralı: tüm store'u değil, ihtiyacınız olan dilimi seçin. Geniş abonelik, sık store güncellemelerinde gereksiz React yeniden render'ı tetikleyebilir.

Seçici örnek düşüncesi: yalnız invalidate için useThree((s) => s.invalidate); yalnız kamera için kamera seçicisi. «Her şeyi alayım» demosu için uygundur, üretim paneli için pahalıdır.

Store alanlarının semantiği Canvas köküne bağlıdır: size host kutusundan gelir (kök sayfa), frameloop politikası kökte mühürlenir. Bu sayfa alanı nasıl seçici okuyacağınızı mühürler; kökü yeniden anlatmaz.

useFrame sözleşmesi

useFrame((state, delta) => { … }) her uygun karede çağrılır. state store anlık görüntüsünü taşır; delta saniye cinsinden kare aralığıdır. Holodepth üretim dilinde: konum/rotasyon için çoğu zaman delta; periyodik dalga için state.clock.elapsedTime (veya eşdeğeri). Three getDelta tuzağının klasik anlatımı zaman omurgasındadır; burada R3F'nin size delta'yı zaten verdiğini bilmek yeterlidir: aynı karede ikinci bir delta icat etmeyin.

Callback içinde ağır iş (JSON parse, texture decode, büyük dizi map) jank üretir. Bu, Platform FPS dilim teşhisine köprüler; Holodepth burada kuralı koyar: useFrame ince olsun, ağır işi kare dışına veya worker'a itin.

Mutasyon: ref hattı

Kare içinde mesh konumunu değiştirmenin yolu Object3D referansıdır: useRef ile mesh'e bağlanıp ref.current.rotation.y += speed * delta. Bu, deklaratif prop yazımını her karede yeniden başlatmaz; React ağacını yeniden uzlaştırmaz.

Deklaratif sayfada mühürlenen «tek kaynak» kuralı burada şöyle okunur: sürekli değişen bir değeri hem position={[x,y,z]} prop hem useFrame ile itmek çift kapıdır. Ya deklaratif (seyrek) ya kare (sık); ikisini aynı alan için yarıştırmayın.

setState zehri

Her karede setState (veya bağlamsız store'a yüksek frekanslı yazmak) React render selini açar. Vitrin 60 Hz ise saniyede 60 uzlaştırma adayıdır; mobil cihazda ürün çöker. Holodepth: UI'ye yansıtılacak değer seyreltilir (her N kare, veya eşik aşımında), 3D hareket ref'te kalır.

Hud / etiket metnini her kare güncellemek istiyorsanız DOM'u ayrı bir düşük frekanslı kanala alın veya üç boyutlu text maliyetini bilinçli kabul edin. Bu bir React temeli dersi değil; R3F köprüsünde frekans diplomatisidir.

Kare ucuz sandığınız setState, aslında ikinci bir motor çalıştırır.

priority: sıra diplomasi

Birden fazla useFrame aynı Canvas'ta yaşar. Sıra önemliyse (önce kamera takip, sonra trail, en sonda ölçüm) priority ile şerit ayırın. Holodepth ürün dilinde yüksek frekanslı «fizik benzeri» itiş ile görsel süs aynı şeritte yarışmamalıdır.

Örnek şeritler · ürün uyarlar
Şerit fikri Tipik iş Not
Erken Kamera / kontrol çıktısını oturtmak Sonraki görseller buna yaslanır
Orta Meshes, trail, hafif animasyon İnce kalsın
Geç Ölçüm, debug overlay bayrağı Üretimi kirletmesin

Sayısal priority değerleri sürüme göre değişebilir; sözleşmeyi «hangi iş hangi şeritte» olarak yazın, magik sayıya tapmayın.

demand ve invalidate köprüsü

Kök frameloop="demand" ise kareler kendiliğinden akmaz. Pointer sonrası, veri geldiğinde veya prop değişince invalidate() gerekir. Canvas sayfasında panel profili bu mühürü koydu; burada köprüyü netleştiririz: useFrame abonesi vardır ama metronom tik atmazsa callback uyanmaz.

Karışık profil: sürekli idle motion isteyen çocuk + demand kök = uyumsuz sözleşme. Ya kökü always yapın ya idle motion'u bırakın ya da kontrollü invalidate üretin. Üçünü birden varsayımlarla birleştirmeyin.

Güvenli kare: simüle abonelik

Örnekler öğretim amaçlıdır; paket sürümünüzü doğrulayın. React hook temeli anlatılmaz. Canvas kökü önceki yapraklarda mühürlü kabul edilir.

Simüle · delta ile dönüş, elapsed ile dalga. Mutasyon ref üzerinden; her karede setState yok.

import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'

const SPIN_RAD_PER_SEC = 1.2
const WAVE_AMP = 0.15

export function SpinningPart({ children }) {
  const root = useRef(null)

  useFrame((state, delta) => {
    const obj = root.current
    if (!obj) return

    // FPS bağımsız dönüş (radyan/s × saniye)
    obj.rotation.y += SPIN_RAD_PER_SEC * delta

    // Dalga: süre tabanlı (elapsed → sin)
    obj.position.y = Math.sin(state.clock.elapsedTime) * WAVE_AMP
  })

  return <group ref={root}>{children}</group>
}

Simüle · seçici invalidate köprüsü. Panel kökü demand iken dış event sonrası tek kare uyandırır; sürekli setState döngüsü açmaz.

import { useEffect } from 'react'
import { useThree } from '@react-three/fiber'

/**
 * seed değişince demand canvas'ı bir kare uyandırır.
 * Sürekli animasyon için kök frameloop="always" tercih edin.
 */
export function WakeBridge({ seed }) {
  const invalidate = useThree((s) => s.invalidate)

  useEffect(() => {
    invalidate()
  }, [seed, invalidate])

  return null
}

Güvenlik: useFrame içinde kullanıcı string'ini eval / dinamik Function ile çalıştırmayın. Uzaktan gelen animasyon eğrisi verisini doğrulayın; unbounded delta (sekme geri dönüşü) için hız tavanı düşünün.

Kare tuzakları

  1. Closure bayatlığı: useFrame'de eski prop yakalamak; güncel değer için ref veya state.clock ile taze okuma.
  2. Koşulsuz ağır iş: her karede alloc / filtre / sort.
  3. Çift metronom: hem kendi rAF'iniz hem R3F döngüsü.
  4. demand unutkanlığı: invalidate yok · «neden dönmüyor?».
  5. UI sel: her kare setState ile HUD.
  6. Şerit kaos: priority'siz birbirini ezen abonelikler.

Picking ve event callback'leri ayrı yapraktır; useFrame içinde her kare raycast yapmak çoğu ürün için pahalıdır. Gerekirse seyreltin veya event yoluna taşıyın.

Üç kare profili

  • 01 · Kare

    Sürekli vitrin

    Kök
    frameloop="always"
    useFrame
    İnce idle / orbit destek
    Risk
    Boşta ağır callback
  • 02 · Kare

    Veri paneli

    Kök
    demand + invalidate
    useThree
    Seçici invalidate / size
    Risk
    always unutmak · pil yenisi
  • 03 · Kare

    Çok abonelikli sahne

    priority
    Kontrol → görsel → ölçüm
    Mutasyon
    ref hattı · setState seyrek
    Risk
    Şeritsiz yarış

Holodepth perspektifleri

Kareyi ince tutun

useFrame bir mikro-işletmendir; uygulama çekirdeği değildir.

Gözü daraltın

useThree'de tüm store'u abone etmek çoğu zaman tembellik maliyetidir.

Frekansı ayırın

3D hareket yüksek frekans; UI metni düşük frekans. İkisini aynı boruya bağlamayın.

Teşhis maddeleri

  1. Render saati ile kare saati karışmış mı?
  2. useThree seçici mi?
  3. useFrame içinde setState yağmuru var mı?
  4. Mutasyon ref üzerinden mi?
  5. delta / elapsed doğru işe mi bağlandı?
  6. demand kökünde invalidate var mı?
  7. priority şeritleri yazılı mı?
  8. FPS SLA veya glTF loader bu sayfaya sızmış mı?

Holodepth içgörüsü

«useFrame koydum dönmedi» çoğu zaman callback hatası değil, kök metronom veya çift kaynaklı alan sorunudur. Önce saati okuyun, sonra tici yazın.

Sonraki kapı: yükleme & Suspense köprüsü

Kare canlıyken asıl yük çoğu zaman asenkron varlıktadır. Sonraki sayfa Yükleme & Suspense köprüsü useLoader, askıya alma ve dispose diplomasisini anlatır. Picking ve imperatif kaçış sonraki yapraklardadır.