我有以下錯誤:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
即使我阻止它在 中執行此操作useEffect,這是如何發生的,如下所示
//component
function LiveStreaming({ title }) {
const [arContent, status] = useContent("story");
useEffect(() => {
if (arContent && arContent !== null) {
console.log("arContent", arContent);
}
}, [arContent]);
}
//useContent
import { useState, useEffect } from "react";
const localCache = {};
async function requestArContent() {
console.log("pinging server for content");
const res = await fetch(`${BASE_URL}/api/books`);
const json = (await res.json()) || {}; //{} so app doesn't crash if no network connection
localCache[title] = json;
}
export function useContent(title) {
const [arContent, setArContent] = useState({});
const [status, setStatus] = useState("unloaded"); //unloaded, loading, loaded
useEffect(() => {
if (!title) {
setArContent({});
} else if (localCache[title]) {
setArContent(localCache[title]);
} else {
setStatus("loading");
requestArContent();
}
}, [title]);
setArContent(localCache[title]);
setStatus("loaded");
return [arContent, status];
}
uj5u.com熱心網友回復:
我認為這個問題是title在不確定requestArContent的useContent鉤定義/檔案,它只是在中定義useContent鉤子函式體。這會導致檢查 wherelocalCache[title]不等于localCache[undefined]set in requestArContent,因此else每次都采用 final并且status狀態在'loaded'和之間切換/翻轉'loading',從而創建渲染回圈。
const localCache = {};
async function requestArContent() {
console.log("pinging server for content");
const res = await fetch(`${BASE_URL}/api/books`);
const json = (await res.json()) || {}; //{} so app doesn't crash if no network connection
localCache[title] = json; // <-- title undefined
}
export function useContent(title) {
const [arContent, setArContent] = useState({});
const [status, setStatus] = useState("unloaded"); //unloaded, loading, loaded
useEffect(() => {
if (!title) {
setArContent({});
} else if (localCache[title]) { // <-- title defined, localCache[title] undefined
setArContent(localCache[title]);
} else {
setStatus("loading");
requestArContent();
}
}, [title]);
setArContent(localCache[title]);
setStatus("loaded");
return [arContent, status];
}
將 passtitle作為引數決議為 ,requestArContent以便使用title密鑰更新快取。
const localCache = {};
async function requestArContent(title) { // <-- consume title arg
console.log("pinging server for content");
const res = await fetch(`${BASE_URL}/api/books`);
const json = (await res.json()) || {}; //{} so app doesn't crash if no network connection
localCache[title] = json;
}
export function useContent(title) {
const [arContent, setArContent] = useState({});
const [status, setStatus] = useState("unloaded"); //unloaded, loading, loaded
useEffect(() => {
if (!title) {
setArContent({});
} else if (localCache[title]) {
setArContent(localCache[title]);
} else {
setStatus("loading");
requestArContent(title); // <-- pass title as arg
}
}, [title]);
setArContent(localCache[title]);
setStatus("loaded");
return [arContent, status];
}
uj5u.com熱心網友回復:
這是發生的事情:
- 你的
LiveStreaming函式呼叫useContent useContent電話setArContent- 這
arContent通過useState鉤子觸發更新 - 這會觸發
useContent鉤子第二次運行(在當前useContent和當前render完成后) - 這會觸發重新渲染(將您送回第一步,讓您進入無限回圈)
此問題的解決方案是useContent僅在實際需要更新時才更新狀態,例如像這樣
export function useContent (title) {
const [arContent, setArContent] = useState({})
const [status, setStatus] = useState('unloaded') //unloaded, loading, loaded
useEffect(() => {
if (!title) {
setArContent({})
} else if (localCache[title]) {
setArContent(localCache[title])
} else {
setStatus('loading')
requestArContent().then(
() => {
setArContent(localCache[title])
setStatus('loaded')
},
err => {
console.error(err)
}
)
}
}, [title])
return [arContent, status]
}
我保持這種方式以更簡單的方式說明核心問題的解決方案,但在我看來它仍然缺少兩件事:
- useEffect 的回呼需要回傳一個回呼來“取消”狀態的更新(否則在 async 操作程序中卸載組件時會出現警告)
- 結果是缺少依賴項,這從來都不是一件好事。即使你不知道現在的時間為什么(我不知道),它總是會在以后咬人
uj5u.com熱心網友回復:
每次都進入到useEffect然后更新狀態,解決你需要使用另一個useState才能知道已經執行了。
const [executed, setExecuted] = useState(false);
const [status, setStatus] = useState("unloaded");
useEffect(() => {
const getData =() =>{
if (!title) {
setArContent({});
} else if (localCache[title]) {
setArContent(localCache[title]);
} else {
setStatus("loading");
requestArContent();
}
setExecuted(true)
}
if(!executed){
getData()
}
}, [title]);
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/353343.html
上一篇:語法錯誤:意外的標記,應為“,”
