javascript - ביטול Async של useEffect עם TypeScript, הדרך הנכונה
יש לי את הדוגמה הפשוטה הזו שמכאב לי:
useEffect(() => {
axios.get(...).then(...).catch(...)
}, [props.foo])
אזהרה: לא ניתן לבצע עדכון מצב של React על רכיב שאינו מותקן
עשיתי קצת מחקר והאחד הזה ברור יותר. נראה ש-TypeScript לא אוהבת את הגישה הזו מכיוון ש-useEffect צריך להחזיר void.
useEffect(() => {
let isSubscribed = true
axios.get(...).then(...).catch(...)
return () => (isSubscribed = false)
}, [props.foo])
TypeScript:
/**
* Accepts a function that contains imperative, possibly effectful code.
*
* @param effect Imperative function that can return a cleanup function
* @param deps If present, effect will only activate if the values in the list change.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#useeffect
*/
function useEffect(effect: EffectCallback, deps?: DependencyList): void;
איך לממש isSubscribed ב-useEffect שלי עם TS?
תודה.
תשובה #1
useEffect עצמו מחזיר void, אך הפונקציה המסופקת ל-useEffect מתויגת כ-EffectCallback. זוהי מוגדרת כך:
// NOTE: callbacks are _only_ allowed to return either void, or a destructor.
// The destructor is itself only allowed to return void.
type EffectCallback = () => (void | (() => void | undefined));
מקור
זה אומר שפונקציית החזרה שלך של האפקט יכולה למעשה להחזיר פונקציה, שצריכה להחזיר void או undefined.
עכשיו אתה יכול לפתור את הבעיה שלך כדי להימנע מקריאה ל-setState עם המשתנה isSubscribed. אבל דרך נוספת (אולי טובה יותר) היא פשוט לבטל את הבקשה.
useEffect(() => {
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('...', { cancelToken: source.token }).then(/**/).catch(e => {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {/* handle error */}
});
return () => source.cancel();
}, [props.foo])
זוהי גם מתועדת בקובץ ה-README.
הבעיה בקוד הנוכחי שלך היא, שהפונקציה המחוסלת שלך מחזירה את הבוליאני isSubscribed. במקום להחזיר אותו, פשוט הכנס את ההקצאה לגוף הפונקציה:
return () => {
isSubscribed = false;
}
