ฉันขอแนะนำให้ดูคำตอบของ Dan Abramov (หนึ่งในผู้ดูแลหลักของ React) ที่นี่ :
ฉันคิดว่าคุณกำลังทำให้มันซับซ้อนกว่าที่ควรจะเป็น
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>
}
ในระยะยาวเราจะไม่สนับสนุนรูปแบบนี้เพราะมันส่งเสริมสภาพการแข่งขัน เช่น - อาจมีอะไรเกิดขึ้นระหว่างการโทรของคุณและสิ้นสุดและคุณอาจมีอุปกรณ์ประกอบฉากใหม่ เราขอแนะนำ Suspense สำหรับการดึงข้อมูลซึ่งจะมีลักษณะดังนี้
const response = MyAPIResource.read();
และไม่มีผลกระทบ แต่ในระหว่างนี้คุณสามารถย้ายข้อมูล async ไปยังฟังก์ชันแยกต่างหากและเรียกใช้
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับใจจดใจจ่อทดลองที่นี่
หากคุณต้องการใช้ฟังก์ชันภายนอกกับ 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>
)
}
ด้วย useCallback useCallback . แซนด์บ็อกซ์
import React, { useState, useEffect, useCallback } from "react";
export default function App() {
const [counter, setCounter] = useState(1);
const fn = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
useEffect(() => {
if (!(counter % 2)) return;
fn();
}, [fn, counter]);
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 } }, [])