Saya menyarankan untuk melihat jawaban Dan Abramov (salah satu pengelola inti React) di sini :
Saya pikir Anda membuatnya lebih rumit dari yang seharusnya.
function Example() {
const [data, dataSet] = useState<any>(null)
useEffect(() => {
async function fetchMyAPI() {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}
fetchMyAPI()
}, [])
return <div>{JSON.stringify(data)}</div>
}
Jangka panjang kami akan mencegah pola ini karena mendorong kondisi balapan. Seperti - apa pun bisa terjadi antara panggilan Anda dimulai dan diakhiri, dan Anda bisa mendapatkan properti baru. Sebagai gantinya, kami akan merekomendasikan Suspense untuk pengambilan data yang lebih mirip
const response = MyAPIResource.read();
dan tidak ada efek. Namun sementara itu Anda dapat memindahkan hal-hal asinkron ke fungsi terpisah dan memanggilnya.
Anda dapat membaca lebih lanjut tentang ketegangan eksperimental di sini .
Jika Anda ingin menggunakan fungsi luar dengan eslint.
function OutsideUsageExample() {
const [data, dataSet] = useState<any>(null)
const fetchMyAPI = useCallback(async () => {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}, [])
useEffect(() => {
fetchMyAPI()
}, [fetchMyAPI])
return (
<div>
<div>data: {JSON.stringify(data)}</div>
<div>
<button onClick={fetchMyAPI}>manual fetch</button>
</div>
</div>
)
}
Dengan useCallback useCallback . Sandbox .
import React, { useState, useEffect, useCallback } from "react";
export default function App() {
const [counter, setCounter] = useState(1);
// if counter is changed, than fn will be updated with new counter value
const fn = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
// if counter is changed, than fn will not be updated and counter will be always 1 inside fn
/*const fnBad = useCallback(() => {
setCounter(counter + 1);
}, []);*/
// if fn or counter is changed, than useEffect will rerun
useEffect(() => {
if (!(counter % 2)) return; // this will stop the loop if counter is not even
fn();
}, [fn, counter]);
// this will be infinite loop because fn is always changing with new counter value
/*useEffect(() => {
fn();
}, [fn]);*/
return (
<div>
<div>Counter is {counter}</div>
<button onClick={fn}>add +1 count</button>
</div>
);
}
useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, [])
eslint
meminta saya untuk menjadikanfetchMyAPI()
sebagai ketergantunganuseEffect
Saat Anda menggunakan fungsi async seperti
ia mengembalikan sebuah promise dan
useEffect
tidak mengharapkan fungsi callback mengembalikan Promise, melainkan ia mengharapkan tidak ada yang dikembalikan atau fungsi dikembalikan.Sebagai solusi untuk peringatan tersebut, Anda dapat menggunakan fungsi asinkron yang memanggil sendiri.
atau untuk membuatnya lebih bersih Anda dapat mendefinisikan sebuah fungsi dan kemudian memanggilnya
solusi kedua akan membuatnya lebih mudah dibaca dan akan membantu Anda menulis kode untuk membatalkan permintaan sebelumnya jika permintaan baru diaktifkan atau menyimpan respons permintaan terbaru dalam status
Kode kerja dan kotak
sumber
useEffect
Anda dapat mengembalikan fungsi untuk melakukan pembersihan seperti berhenti berlangganan acara. Ketika Anda menggunakan fungsi async, Anda tidak dapat mengembalikan apa pun karenauseEffect
tidak akan menunggu hasilnyaSampai Bereaksi menyediakan cara yang lebih baik, Anda dapat membuat pembantu,
useEffectAsync.js
:Sekarang Anda dapat meneruskan fungsi async:
sumber
useAsyncEffect
seperti yang Anda tulis dapat dengan mudah menyesatkan seseorang untuk berpikir jika mereka mengembalikan fungsi pembersihan dari efek asinkronnya, fungsi itu akan dijalankan pada waktu yang tepat. Hal ini dapat menyebabkan kebocoran memori atau bug yang lebih buruk, jadi kami memilih untuk mendorong orang-orang untuk memfaktorkan ulang kode mereka untuk membuat "lapisan" fungsi asinkron yang berinteraksi dengan siklus hidup React lebih terlihat, dan akibatnya perilaku kode diharapkan lebih disengaja dan benar.Saya membaca pertanyaan ini, dan merasa cara terbaik untuk mengimplementasikan useEffect tidak disebutkan dalam jawaban. Katakanlah Anda memiliki panggilan jaringan, dan ingin melakukan sesuatu setelah Anda mendapat tanggapan. Demi kesederhanaan, mari simpan respons jaringan dalam variabel status. Seseorang mungkin ingin menggunakan tindakan / peredam untuk memperbarui penyimpanan dengan respons jaringan.
Referensi => https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
sumber
void operator dapat digunakan di sini.
Dari pada:
atau
Anda bisa menulis:
Ini sedikit lebih bersih dan lebih cantik.
Efek asinkron dapat menyebabkan kebocoran memori, jadi penting untuk melakukan pembersihan pada pelepasan komponen. Dalam kasus pengambilan ini akan terlihat seperti ini:
sumber
mencoba
sumber
Bagi pembaca lain, kesalahan bisa berasal dari fakta bahwa tidak ada tanda kurung yang membungkus fungsi asinkron:
Mempertimbangkan fungsi async initData
Kode ini akan menyebabkan kesalahan Anda:
Tapi yang ini, tidak akan:
(Perhatikan tanda kurung di sekitar initData ()
sumber