<StrictMode>, içindeki her şey için yalnızca geliştirmede ekstra kontroller açan bir React bileşenidir. Her bileşeni iki kez render eder, mount sırasında her efektin kurulumunu, temizlemesini ve yeniden kurulumunu çalıştırır, ref callback'lerini iki kez çalıştırır ve kullanımdan kalkan API'ler hakkında uyarır. useEffect'in geliştirmede "iki kez çalışmasının" nedeni budur. Bir production derlemesinde hiçbir şey yapmaz.
Onu uygulamanı sararak açarsın, genellikle main.jsx içinde:
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
Bu sayfadaki önizlemeler bir production derlemesi gibi çalışır, bu yüzden StrictMode'un onlarda görünür bir etkisi olmazdı. Bunun yerine aşağıdaki her örnekte StrictMode'un yakalamak için var olduğu türden bir hata var ve onu elle tetiklemeni sağlıyor. Burada bir efekt bir document tıklama dinleyicisi ekliyor ve onu hiç kaldırmıyor. Paneli birkaç kez gizle ve göster, sonra sayfaya tıkla.
Her Show bir dinleyici daha ekler ve hiçbiri kaldırılmaz, bu yüzden tek bir tıklama mount başına bir kez kayıt yazar. Bu, bir kullanıcının bir paneli açıp kapatarak yol açabileceği bir sızıntıdır. StrictMode bunu daha ilk mount'ta gösterirdi: geliştirmede mount eder, unmount eder ve yeniden mount eder, bu yüzden düğmeye dokunmadan her tıklamada iki kayıt satırı görürdün.
Efektler: kurulum, temizleme, kurulum
Mount sırasında StrictMode efektini, sonra temizlemesini, sonra efekti yeniden çalıştırır. Bir kullanıcının bir ekrandan ayrılıp geri geldiğinde olanı simüle eder ve temizlemenin kurulumunu geri aldığını kontrol eder. Alıyorsa ikinci kurulum her şeyi tek bir kurulumun bırakacağı gibi bırakır ve yanlış hiçbir şey görmezsin. Almıyorsa hata hemen ortaya çıkar.
Kaydedici için çözüm, eklediği fonksiyonun aynısını kaldıran bir temizlemedir:
İstediğin kadar aç kapa: kaydedici gösterilirken her tıklama bir satır yazar. Geliştirmede StrictMode altında konsol setup, cleanup, setup ile başlardı ve uygulama yine doğru davranırdı. Bu sıra sağlıklı bir efektin işaretidir, kapatılacak bir sorun değil.
Temizleme gerektiren yaygın efektler: olay dinleyicileri, setInterval ve setTimeout, abonelikler, WebSocket ya da sohbet bağlantıları ve bileşen gittiyse yanıtı yok sayılması gereken istekler. useEffect sayfası her biri için temizleme kalıbını gösteriyor.
Render'lar: iki kez çağrılır
StrictMode ayrıca her render için bileşen fonksiyonunu iki kez çağırır (ve useState, useMemo ve useReducer'a aktardığın fonksiyonları, class'larda constructor, render ve shouldComponentUpdate'i). React bir çağrının sonucunu tutar, diğerini atar. Saf bir bileşen iki seferde de aynı JSX'i döndürür, bu yüzden hiçbir şey değişmez.
Render sırasında kendi dışındaki bir şeyi değiştiren bir bileşen saf değildir ve onu iki kez çağırmak değişikliğin iki kez olmasına yol açar. Bu bileşen, prop olarak aldığı bir diziye bir "rendered at" girişi ekliyor:
Her yeniden render kimsenin istemediği bir giriş ekler. Burada bunu yalnızca tıkladıktan sonra fark edersin. StrictMode altında ilk render zaten bir yerine iki yeni giriş gösterirdi. Çözüm, değiştirmeden render sırasında hesaplamaktır: const shown = [...entries, 'extra'].
React 19 bir ayrıntı ekler: çift render sırasında useMemo ve useCallback, iki kez hesaplamak yerine ilk çağrının sonucunu yeniden kullanır.
Ref callback'leri
React 19'dan beri StrictMode ref callback'lerini de mount sırasında iki kez çalıştırır: bağla, temizle, bağla. Bir dinleyici ekleyen ya da düğümü bir yere kaydeden bir ref callback'inin, tıpkı bir efekt gibi, bir temizleme döndürmesi gerekir:
<div
ref={(node) => {
const observer = new ResizeObserver(onResize);
observer.observe(node);
return () => observer.disconnect();
}}
/>
Kullanımdan kalkan API uyarıları
StrictMode, çoğunlukla class bileşenlerinde, eski UNSAFE_componentWillMount, UNSAFE_componentWillReceiveProps ve UNSAFE_componentWillUpdate yaşam döngüleri gibi çıkış yolundaki API'ler hakkında uyarır. String ref'ler ve findDOMNode gibi eskiden uyardığı bazı API'ler React 19'dan tamamen kaldırıldı.
Uygulamanın bir kısmı için açmak
<StrictMode> normal bir bileşendir, bu yüzden ağacın yalnızca bir kısmını sarabilirsin. Bu, onu büyük bir uygulamada benimserken yardımcı olur: yeni ekranlarla başla ve genişlet.
function App() {
return (
<>
<Header />
<StrictMode>
<Sidebar />
<Content />
</StrictMode>
<Footer />
</>
);
}
Sidebar ve Content (ve render ettikleri her şey) kontrolleri alır; Header ve Footer almaz. Strict bir kısmın içindeki bir alt ağaç için onu kapatmanın bir yolu yoktur.
Varsayılan olarak açık olduğu yerler:
- Vite: React şablonu
main.jsxiçinde<App />'i<StrictMode>ile sarar. - Next.js: App Router onu varsayılan olarak açar;
next.config.jsiçindekireactStrictModeonu kontrol eder.
Production'da hiçbir şey yapmaz
Bir production derlemesi <StrictMode>'u yok sayar: bir render, bir efekt çalışması, uyarı yok. Yani çift çağrılar kullanıcılarına hiçbir şeye mal olmaz ve dağıtmadan önce sarmalayıcıyı kaldırmak için bir neden yoktur.
Geliştirmede çift bir efekt bir şeyi bozuyorsa, örneğin iki kez gönderilen bir istek ya da iki kez kaydedilen bir analitik olayı, bu bir bilgidir. Çoğu zaman çözüm bir temizlemedir (bir istek için bir ignore bayrağı, bir bağlantı için bir bağlantı kesme). Gerçekten uygulama yüklemesi başına bir kez olması gereken bir şey için, örneğin bir SDK'yı başlatmak, onu herhangi bir bileşenin dışında modül düzeyinde çalıştır ya da modül düzeyinde bir bayrakla koru.
let didInit = false;
function App() {
useEffect(() => {
if (didInit) return;
didInit = true;
initAnalytics(); // runs once per page load, even in StrictMode
}, []);
}
İkinci efekt çalışmasını atlayan bir ref şeklindeki yaygın geçici çözümden kaçın. Eksik temizlemeyi düzeltmeden uyarıyı gizler ve hata, bileşen ilk kez gerçekten unmount olup yeniden mount olduğunda, yukarıdaki kaydedicide olduğu gibi, geri gelir.
Sıkça Sorulan Sorular
React StrictMode ne yapar?
Yalnızca geliştirmede, içindeki her bileşeni iki kez render eder, bileşen mount olduğunda her efektin kurulumunu, temizlemesini ve yeniden kurulumunu çalıştırır, ref callback'lerini aynı şekilde iki kez çalıştırır ve kullanımdan kalkan API'ler hakkında uyarır. Fazladan çağrılar saf olmayan render'ları ve temizlemesi eksik efektleri ortaya çıkarır.
useEffect'im neden iki kez çalışıyor?
Çünkü bileşen <StrictMode> içinde ve bir geliştirme derlemesi çalıştırıyorsun. React onu mount eder, bir unmount'u simüle eder (temizlemen çalışır) ve yeniden mount eder. İkinci kurulum bir hataya yol açıyorsa efektin temizlemesi eksiktir.
StrictMode production'ı etkiler mi?
Hayır. Bir production derlemesi, <StrictMode> olsun ya da olmasın, bir kez render eder ve her efekti bir kez çalıştırır. Onu kodunda bırakabilirsin.
StrictMode nasıl kapatılır?
Genellikle main.jsx ya da index.js içindeki <StrictMode> sarmalayıcısını kaldır ya da next.config.js içinde reactStrictMode: false ayarla. Temizlemeyi düzeltmek genellikle daha iyidir: çift çalışma, gerçek kullanıcıların karşılaşabileceği bir hataya işaret ediyor.
console.log neden iki kez yazdırılıyor?
StrictMode geliştirmede her render için bileşen fonksiyonunu iki kez çağırır. React DevTools ayarlarında ikinci çağrının kayıtlarını soluklaştırabilir ya da gizleyebilir.