React use ile yükleme işlevi nasıl çağrılır


210

UseEffect kanca her değişikliği işleve geçirilen çalışacaktır yanıt verin. Bu, yalnızca istenen özellikler değiştiğinde çağrılabilmesi için optimize edilebilir.

componentDidMountDeğişikliklerde yeniden başlatma işlevini çağırmak ve yeniden çağırmamak istersem ne olur ? Bir varlığı yüklemek istiyorum, ancak yükleme işlevinin bileşenden herhangi bir veriye ihtiyacı olmadığını varsayalım. useEffectKancayı kullanarak bunu nasıl yapabiliriz ?

class MyComponent extends React.PureComponent {
    componentDidMount() {
        loadDataOnlyOnce();
    }
    render() { ... }
}

Kancalarla bu şöyle görünebilir:

function MyComponent() {
    useEffect(() => {
        loadDataOnlyOnce(); // this will fire on every change :(
    }, [...???]);
    return (...);
}

Yanıtlar:


396

Yalnızca useEffectilk oluşturma işleminden sonra verilen işlevi çalıştırmak istiyorsanız, ona ikinci argüman olarak boş bir dizi verebilirsiniz.

function MyComponent() {
  useEffect(() => {
    loadDataOnlyOnce();
  }, []);

  return <div> {/* ... */} </div>;
}

27
Alternatif olarak, verileri almak için kullandığınız parametreler (örneğin, bir kullanıcı kimliği) varsa, o dizide kullanıcı kimliğini iletebilirsiniz ve eğer değiştirilirse bileşen verileri yeniden getirecektir. Kullanım durumlarının çoğu bu şekilde çalışacaktır.
trixn

4
evet ... atlama hakkında daha fazla bilgi burada belgelendi: reatjs.org/docs/…
Melounek

Bu en basit cevap gibi görünüyor, ancak ESLint şikayet ediyor ... bu konudaki diğer cevaba bakınız stackoverflow.com/a/56767883/1550587
Simon Hutchison

LoadDataOnlyOnce öğesini bağımlılık dizisine iletmeniz yeterlidir. İşe yarıyor mu?
jpmarks

88

TL; DR

useEffect(yourCallback, []) - geri aramayı yalnızca ilk oluşturma işleminden sonra tetikleyecektir.

Detaylı açıklama

useEffectbileşenin her oluşturulmasından sonra varsayılan olarak çalışır (böylece bir etkiye neden olur).

useEffectBileşeninize yerleştirirken React'a geri çağrıyı bir efekt olarak çalıştırmak istediğinizi söylersiniz. React, oluşturma işleminden sonra ve DOM güncellemelerini gerçekleştirdikten sonra efekti çalıştıracaktır.

Yalnızca bir geri arama iletirseniz - geri arama her oluşturma işleminden sonra çalışır.

İkinci bir bağımsız değişken (dizi) iletilirse, React ilk oluşturma işleminden sonra ve dizideki öğelerden biri her değiştiğinde geri aramayı çalıştırır. örneğin yerleştirirken useEffect(() => console.log('hello'), [someVar, someOtherVar])- geri arama ilk işlemden sonra ve bir someVarveya someOtherVardeğiştirilen herhangi bir işlemden sonra çalışır .

İkinci bağımsız değişkeni boş bir dizi geçirerek React, dizinin her oluşturulmasından sonra karşılaştırılacak ve hiçbir şeyin değiştirilmediğini görecek ve böylece geri aramayı yalnızca ilk oluşturma işleminden sonra çağıracaktır.


69

useMountEffect kancası

Bir işlevi bileşen montajlarından sonra yalnızca bir kez çalıştırmak, uygulama ayrıntılarını gizleyen kendine ait bir kancayı haklı çıkaracak kadar yaygın bir kalıptır.

const useMountEffect = (fun) => useEffect(fun, [])

Herhangi bir fonksiyonel bileşende kullanın.

function MyComponent() {
    useMountEffect(function) // function will run only once after it has mounted. 
    return <div>...</div>;
}

UseMountEffect kancası hakkında

useEffectİkinci bir dizi bağımsız değişkeni ile birlikte kullanıldığında , React montajdan (ilk oluşturma) sonra ve dizideki değerler değiştikten sonra geri aramayı çalıştırır. Boş bir dizi geçirdiğimizden, yalnızca montajdan sonra çalışır.


19
ESLint kuralı "tepki kancaları / kapsamlı depsler" her zaman boş bağımlılık listelerinde başarısız olacağından yanıtınızı tercih ederim. Örneğin, ünlü oluştur-reaksiyon-uygula şablonu bu kuralı uygular.
Dynalon

1
@Dynalon ile tamamen aynı fikirde. ESLint kuralına müdahale etmediği için bu kabul edilen çözüm olmalıdır
Mikado68

Teşekkürler @Dynalon ve Mikado68 :-). Karar OP'nin bir ayrıcalığıdır. Yorumlarınız hakkında bilgilendirildim, ancak OP değildi. Doğrudan soru üzerine yorum yaparak ona önerebilirsiniz.
Ben Carp

2
Artık useMountefekt işlevinizin sahne malzemelerinden bir şeye ihtiyacı olduğunda ancak linter warnig olmadan bu değer değişse bile asla tekrar çalıştırılması gerekmediğinde kullanabilirsiniz: useEffect(()=>console.log(props.val),[])eksik bağımlılık uyarısı olacak, ancak useMount(()=>console.log(props.val))bir uyarıya neden olmayacak, ancak "çalışıyor". Eşzamanlı modda bir sorun olup olmayacağından emin değilim.
HMR

1
Bunu beğendim :) Daha önce devletle aynı sebep; ESLint kuralı bu konuda şikayet etmeyecek, artı adı boş bir diziden daha kolay
Frexuz

20

Boş bir diziyi ikinci argüman olarak iletin useEffect. Bu, React'e, dokümanları alıntılayarak etkili bir şekilde söyler :

Bu, React'a etkinizin sahne veya durumdaki herhangi bir değere bağlı olmadığını söyler, bu yüzden asla yeniden çalıştırılması gerekmez.

İşte çalıştığını göstermek için çalıştırabileceğiniz bir snippet:

function App() {
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        setUser(data.results[0]);
      });
  }, []); // Pass empty array to only run once on mount.
  
  return <div>
    {user ? user.name.first : 'Loading...'}
  </div>;
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>


4

Bir mountişlevi tanımlamayı seviyorum , EsLint'i de aynı şekilde kandırıyor useMountve onu daha açıklayıcı buluyorum.

const mount = () => {
  console.log('mounted')
  // ...

  const unmount = () => {
    console.log('unmounted')
    // ...
  }
  return unmount
}
useEffect(mount, [])

-2

Hile, useEffect'in ikinci bir parametre almasıdır.

İkinci parametre, yeniden oluşturma işleminden önce bileşenin değiştiğinden emin olmak için denetleyeceği bir değişkenler dizisidir. Burada kontrol etmek istediğiniz sahne ve durum parçalarını koyabilirsiniz.

Veya hiçbir şey koymayın:

import React, { useEffect } from 'react';

function App() {
  useEffect(() => {

    // Run! Like go get some data from an API.

  }, []); //Empty array as second argument

  return (
    <div>
      {/* Do something with data. */}
    </div>
  );
}

Bu, useEffect öğesinin yalnızca bir kez çalışmasını sağlar.

Dokümanlardan not:

Bu optimizasyonu kullanırsanız, dizinin bileşen kapsamındaki (sahne ve durum gibi) zamanla değişen ve efekt tarafından kullanılan tüm değerleri içerdiğinden emin olun. Aksi takdirde, kodunuz önceki görüntülemelerin eski değerlerine referansta bulunur.


4
Kelimenin tam anlamıyla CSS Tricks'ten kopyalama / yapıştırma yönteminiz varsa, yapabileceğiniz en az şey kaynağınıza kredi vermektir. css-tricks.com/run-useeffect-only-once
burtyish
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.