日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
React中常見的八個錯誤,如何避免?

大家好,我是 CUGGZ。

發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務至上”的服務理念,堅持“二合一”的優(yōu)良服務模式,真誠服務每家企業(yè),認真做好每個細節(jié),不斷完善自我,成就企業(yè),實現(xiàn)共贏。行業(yè)涉及成都自上料攪拌車等,在成都網(wǎng)站建設、網(wǎng)絡營銷推廣、WAP手機網(wǎng)站、VI設計、軟件開發(fā)等項目上具有豐富的設計經(jīng)驗。

今天來分享在 React 開發(fā)中常見的一些錯誤,以及如何避免這些錯誤。理解這些問題背后的細節(jié),防止犯下類似的錯誤。

1. 組件卸載后執(zhí)行狀態(tài)更新

 Can’t perform a React state update on an unmounted component

這個報錯就是因為在組件樹的某個地方,狀態(tài)更新被觸發(fā)到已經(jīng)卸載的組件上了。也就是說,我們不能在組件銷毀后更新 state,防止出現(xiàn)內存泄漏。

const Component = () => {
const [data, setData] = useState(null);

useEffect(() => {
fetchAsyncData().then((data) => setData(data));
}, []);


};

比如,在請求數(shù)據(jù)時,由于跳轉到了B頁面,A頁面的數(shù)據(jù)請求還在進行中,但是頁面已經(jīng)銷毀了,就會出現(xiàn)這種情況。那該如何解決這個問題呢?有兩種方法:

(1)組件卸載時取消異步請求

第一種方法(推薦),就是在組件卸載時取消異步請求。一些異步請求庫提供了取消異步請求的方法。如果沒有使用第三方庫,可以使用 AbortController 來取消。這種方法本質上就是在組件卸載時取消副作用:

const Component = () => {
const [data, setData] = useState(null);

useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal }).then((data) => setData(data));
return () => {
controller.abort();
}
}, []);


};

(2)跟蹤組件是否已掛載

另外,可以跟蹤組件的掛載狀態(tài),如果還沒掛載或已經(jīng)卸載,返回 false;否則返回 true:

const Component = () => {
const [data, setData] = useState(null);
const isMounted = useRef(true);

useEffect(() => {
fetchAsyncData().then(data => {
if(isMounted.current) {
setData(data);
}
});

return () => {
isMounted.current = false;
};
}, []);


}

不過,不建議使用這種方法。這樣保留了未掛載組件的引用,可能會導致內存泄漏和性能問題。

2. 渲染列表時不使用 key

 Warning: Each child in a list should have a unique key prop

React 開發(fā)中最常見的就是遍歷數(shù)組來渲染組件。在JSX中,可以使用Array.map將該邏輯嵌入到組件中,并在回調中返回所需的組件。如下:

import { Card } from "./Card";

const data = [
{ id: 1, text: "JavaScript" },
{ id: 2, text: "TypeScript" },
{ id: 3, text: "React" }
];

export default function App() {
return (

{data.map((content) => (



))}

);
}

這樣會收到如下警告:Warning: Each child in a list should have a unique key prop?,這表示需要給生成的每個組件一個唯一的key。所以,要在map?回調返回的JSX的最外層元素添加一個key值,該值應該是一個字符串或者數(shù)字,并且在這個組件列表中應該是唯一的。

export default function App() {
return (

{data.map((content) => (



))}

);
}

盡管不遵守這個要求也不會導致應用崩潰,但它可能會導致一些意外的情況。React 會使用這些key來確定列表中的哪些子項發(fā)生了更改,并使用此信息來確定可以重用先前 DOM 的哪些部分,以及在重新渲染組件時應該重新計算哪些部分。因此,建議添加 key。

3. Hooks 調用順序錯誤

 React Hook "useXXX" is called conditionally. React Hooks must be called in the exact same order in every component render

先來看下面的代碼:

const Toggle = () => {
const [isOpen, setIsOpen] = useState(false);

if (isOpen) {
return
{}
;
}
const openToggle = useCallback(() => setIsOpen(true), []);
return ;
};

當 isOpen? 的值為true?時,就會直接return?那個div?元素。這樣當isOpen?的值為true和false時useCallback? Hook的調用順序就不一致了。這時React就會警告我們:React Hook "useCallback" is called conditionally. React Hooks must be called in the exact same order in every component render。這其實就是React官方文檔中所說的,。遵守這條規(guī)則才能確保 Hook 在每一次渲染中都按照同樣的順序被調用。

可以這樣來修改上面的代碼:

const Toggle = () => {
const [isOpen, setIsOpen] = useState(false);
const openToggle = useCallback(() => setIsOpen(true), []);

if (isOpen) {
return
{/* ... */}
;
}
return ;
};

4. useEffect 缺少依賴

 React Hook useEffect has a missing dependency: 'XXX'. Either include it or remove the dependency array

先來看看 React 官網(wǎng)給出的例子:

function Example({ someProp }) {
function doSomething() {
console.log(someProp);
}

useEffect(() => {
doSomething();
}, []);
}

在useEffect?中定義空的依賴數(shù)組是不安全,因為它調用的 doSomething? 函數(shù)使用了 someProp?。這時就會報錯:React Hook useEffect has a missing dependency: 'XXX'. Either include it or remove the dependency array?。當props?中的someProp?發(fā)生變化時,函數(shù)doSomething?的結果就會發(fā)生變化,然而useEffect的依賴數(shù)組為空,所以就不會執(zhí)行回調中的內容。

有兩種方式來解決這個問題:

  • 在useEffect中聲明其所需函數(shù),這種方式適用于只需要調用一次的函數(shù),比如初始化函數(shù):
function Example({ someProp }) {
useEffect(() => {
function doSomething() {
console.log(someProp);
}
doSomething();
}, [someProp]);
}
  • 使用useCallback來定義依賴項,確保當自身依賴發(fā)生改變時函數(shù)主體也會改變:
function Example({ someProp }) {
const doSomething = useCallback(() => {
console.log(someProp);
}, [someProp])

useEffect(() => {
doSomething();
}, [doSomething]);
}

5. 重新渲染過多

 Too many re-renders. React limits the number of renders to prevent an infinite loop

這個報錯就是說重新渲染過多。React 限制渲染的數(shù)量以防止無限循環(huán)。當組件在很短的時間有太多狀態(tài)更新時,就可能會發(fā)生這種情況。導致無限循環(huán)的最常見原因是:

  • 直接在渲染中執(zhí)行狀態(tài)更新;
  • 未向事件處理程序提供適當?shù)幕卣{。

如果遇到這個警告,可以檢查組件的這兩個方面:

const Component = () => {
const [count, setCount] = useState(0);

setCount(count + 1); // 渲染中的狀態(tài)更新

return (

{/* onClick 沒有正確的回調 */}


);
}

6. 渲染的單條數(shù)據(jù)為對象

 Objects are not valid as a React child / Functions are not valid as a React child

在 React 中,我們可以在組件中渲染到 DOM 中的東西有很多,比如:HTML標簽、JSX元素、原始 JavaScript 值、JavaScript 表達式等。但是不能將對象和函數(shù)渲染到 DOM 中,因為這兩個值不會解析為有意義的值,如果渲染了對象或函數(shù),就會報上面的錯誤。解決這個問題的方法很簡單,就是檢查渲染的內容是否是有效的值:

const Component = ({ body }) => (

{/* */}


{/* 必須確保 body 是有效的 React child */}
{body}


);

7. 相鄰JSX元素沒有包裝在封閉標記中

 Adjacent JSX elements must be wrapped in an enclosing tag

這個報錯就是說相鄰JSX元素必須包裝在封閉標記中,也就是必須要有一個根元素:

const Component = () => (


);

從 React 開發(fā)人員的角度來看,這個組件只會在另一個組件內部使用。因此,在他們的心智模型中,從一個組件返回兩個元素是有意義的,因為生成的 DOM 結構將是相同的,無論外部元素是在此組件中定義還是在父組件中定義。但是,React 無法做出這種假設。該組件可能會在根目錄中使用并破壞應用,因為它會導致無效的 DOM 結構。

所以,應該始終將組件返回的多個 JSX 元素包裝在一個封閉標記中??梢允且粋€元素、一個組件或者 React Fragment:

const Component = () => (




);

或者直接使用一個空標簽來包裝兩個 JSX 元素:

const Component = () => (
<>



);

8. 使用舊的狀態(tài)

先來看一個計數(shù)器的例子:

const Increaser = () => {
const [count, setCount] = useState(0);

const increase = useCallback(() => {
setCount(count + 1);
}, [count]);

const handleClick = () => {
increase();
increase();
increase();
};

return (
<>

Counter: {count}


);
}

這里的handleClick?方法會在點擊按鈕后執(zhí)行三次增加狀態(tài)變量count?的操作。那么點擊一次是否會增加3呢?事實并非如此。點擊按鈕之后,count只會增加1。問題就在于,當我們點擊按鈕時,相當于下面的操作:

const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};

當?shù)谝淮握{用setCount(count + 1)?時是沒有問題的,它會將count?更新為1。接下來第2、3次調用setCount?時,count?還是使用了舊的狀態(tài)(count為0),所以也會計算出count為1。發(fā)生這種情況的原因就是狀態(tài)變量會在下一次渲染才更新。

解決這個問題的辦法就是,使用函數(shù)的方式來更新狀態(tài):

const Increaser = () => {
const [count, setCount] = useState(0);

const increase = useCallback(() => {
setCount(count => count + 1);
}, [count]);

const handleClick = () => {
increase();
increase();
increase();
};

return (
<>

Counter: {count}


);
}

這樣改完之后,React就能拿到最新的值,當點擊按鈕時,就會每次增加3。所以需要記?。?/p>

setValue(prevValue => prevValue + someResult)


分享標題:React中常見的八個錯誤,如何避免?
網(wǎng)站鏈接:http://m.5511xx.com/article/cccidec.html