Geçersiz Hook Çağrıları
Muhtemelen aşağıdaki hatayı aldığınız için buradasınız:
Hooks can only be called inside the body of a function component.
3 yaygın sebebi vardır.
- React ve React DOM sürümleriniz uyumsuz olabilir.
- Hook Kuralları‘nı çiğnemiş olabilirsiniz.
- Aynı uygulama içerisinde birden fazla React kopyası mevcuttur.
Tüm bu durumları tek tek inceleyelim.
React ve React DOM sürümlerinin uyumsuz olması
Henüz Hook desteklemeyen react-dom
(< 16.8.0) veya react-native
(< 0.59) bir sürüm kullanıyor olabilirsiniz. Kullanılan sürümü öğrenmek için npm ls react-dom
veya npm ls react-native
komutlarını çalıştırabilirsiniz. Eğer birden fazla sürüm bulundu ise sorun bundan olabilir (devamı aşağıda).
Hook Kurallarını Çiğnemek
Hook’ları yalnızca fonksiyon bileşenlerinin içinde kullanabilirsiniz:
- ✅ Hook’ları fonksiyon bileşeninin en tepesinde çağırın.
- ✅ Özel Hook’ların içinde de en tepede çağırın.
Bu konuya dair daha fazlasını Hook kuralları bölümünde öğrenin.
function Counter() {
// ✅ İyi: fonksiyon bileşenin tepesinde çağırılmış const [count, setCount] = useState(0); // ...
}
function useWindowWidth() {
// ✅ İyi: özel Hook'un tepesinde çağırılmış const [width, setWidth] = useState(window.innerWidth); // ...
}
Karışıklığı önlemek için, diğer durumlarda Hook’ları kullanmak desteklenmez:
- 🔴 Sınıf bileşenin içinde çağırmayın.
- 🔴 Olay yöneticisi içinde çağırmayın.
- 🔴
useMemo
,useReducer
, veyauseEffect
içinde Hook’ları kullanmayın
Bu kuralları çiğnerseniz aşağadıki hataları görebilirsiniz.
function Bad1() {
function handleClick() {
// 🔴 Kötü: Olay yöneticisi içinde (düzeltmek için dışarı taşı!) const theme = useContext(ThemeContext); }
// ...
}
function Bad2() {
const style = useMemo(() => {
// 🔴 Kötü: useMemo içinde (düzeltmek için dışarı taşı!) const theme = useContext(ThemeContext); return createStyle(theme);
});
// ...
}
class Bad3 extends React.Component {
render() {
// 🔴 Kötü: Sınıf bileşenin içinde useEffect(() => {}) // ...
}
}
eslint-plugin-react-hooks
eklentisini kullanarak bu hataları yakalayabilirsiniz.
Not
Özel Hook’lar başka Hook’ları çağıralabilir(tüm amaçları budur). Bu işe yarar, çünkü Hook’lar yalnızca bir fonksiyon bileşeni içerisindeszn çağırılabiliyordu.
Birden Fazla React
Hook’ların çalışması için, uygulama kodunuza import ettiğiniz react
ile react-dom
içerisindeki react
aynı olmalıdır.
Eğer bunlar farklı ise bu uyarıyı alabilirsiniz . Yanlışlıkla 2 farklı react sürümüne ait paket kurulmuş olabilir.
Paket yönetimi için node kullanıyorsanız bu komutu proje içerisinde çalıştırabilirsiniz:
npm ls react
Eğer birden fazla react sürümü görürseniz bu sorunu çözmeniz gerekmektedir. Örneğin yanlış kullandığınız bir kütüphane React
‘ı bağımlılık olarak belirtir(aynı react’ı kullanmak yerine).Bu kütüphane düzeltilinceye kadar, Yarn resolutions olası geçici çözümdür.
Ayrıca, bazı log’lar ekleyerek ve sunucuyu yeniden başlatarak bu sorunu çözmeyi deneyebilirsiniz:
// Bunu node_modules/react-dom/index.js dosyasına ekleyin
window.React1 = require('react');
// Bunu bileşen dosyanıza ekleyin
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);
Eğer ekrana false
yazıyorsa iki farklı react olabilir ve bunun neden olduğunu çözmeniz gerekebilir. Bu sorun, topluluğun karşılaştığı bazı genel nedenleri içerir.
Bu sorun, npm link
veya eşdeğer bir komut kullandığınızda ortaya çıkabilir. Bu durumda paket yöneticiniz, biri uygulama içerisinde bir diğeri kütüphane klasörü içerisinde olmak üzere 2 farklı React görebilir.
myapp
ve mylib
kardeş klasöler olduğu varsayılırsa olası bir düzeltme için mylib
klasöründe npm link
komutu çalıştırılmalıdır.Bu, kütüphanenin uygulama içerisindeki React kopyasını kullanmasını sağlar
Not
Genel olarak, React bir sayfada birden fazla bağımsız kopya kullanmayı destekler(örneğin bir uygulama ve üçüncü-party bir eklenti kullanıyorsa).
require('react')
sadece, bileşen içerisindeki ilereact-dom
içerisindeki sürümler farklı ise çalışmaz.
Diğer Nedenler
Bunların hiçbiri işe yaramaz ise lütfen bize bu sorun başlığı altında yorum bırakın.Size yardımcı olmaya çalışacağız.Küçük bir uygulama oluşturarak tekrar deneyebilirsiniz — belki hatayı bu şekilde bulabilirsiniz.