React Native從類組件到函數(shù)組件詳解
1. 發(fā)展趨勢(shì)
React Native社區(qū)中的趨勢(shì)是朝向使用函數(shù)組件(Functional Components)和Hooks的方向發(fā)展,而不是使用類組件(Class Components)。
React Native自推出Hooks API以來,函數(shù)組件和Hooks的使用變得更加普遍和推薦。Hooks提供了更簡潔、可讀性更高的代碼,并且在狀態(tài)管理、生命周期等方面提供了更強(qiáng)大的功能。使用Hooks可以更容易地共享邏輯和狀態(tài)邏輯,而無需使用類組件的復(fù)雜結(jié)構(gòu)。
以下是一些關(guān)于為什么React Native社區(qū)更傾向于使用函數(shù)組件和Hooks的理由:
- 可讀性和簡潔性: 函數(shù)組件通常比類組件更短,更易于閱讀和理解。Hooks的引入使得在函數(shù)組件中管理狀態(tài)和副作用變得更為直觀。
- 邏輯復(fù)用: Hooks使得邏輯的復(fù)用更加容易。你可以使用自定義Hooks將組件之間的邏輯進(jìn)行抽象和共享,而不需要使用高階組件或渲染屬性。
- 更直觀的副作用處理: 使用useEffect等Hooks來處理副作用相對(duì)于類組件中的生命周期方法更為直觀。
- 更容易集成現(xiàn)代JavaScript特性: 使用函數(shù)組件和Hooks可以更容易地與ES6+和TypeScript等現(xiàn)代JavaScript特性集成。
- 更好的性能優(yōu)化: Hooks使得React能夠更好地進(jìn)行性能優(yōu)化,并且React Native的未來版本也更加注重性能。
2. Hooks vs Class
Hooks 提供了在函數(shù)組件中執(zhí)行副作用和訪問狀態(tài)的能力。
下面是一些常見的 Hooks 及其在類組件中對(duì)應(yīng)的生命周期方法:
1.useState - setState:
- 函數(shù)組件: 使用 useState 來聲明和更新狀態(tài)。
- 類組件: 使用 this.setState 來更新狀態(tài)。
2.useEffect - componentDidMount, componentDidUpdate, componentWillUnmount:
函數(shù)組件: 使用 useEffect 來執(zhí)行副作用,可以模擬生命周期方法的行為。
類組件:
componentDidMount: 在組件掛載后調(diào)用。componentDidUpdate: 在組件更新后調(diào)用。componentWillUnmount: 在組件卸載前調(diào)用。
useEffect(() => {
// componentDidMount 和 componentDidUpdate 的邏輯
return () => {
// componentWillUnmount 的邏輯
};
}, [dependencies]);3.useContext - contextType:
- 函數(shù)組件:使用 useContext 來訪問 React 上下文。
- 類組件:使用 contextType 來訪問 React 上下文。
4.useReducer - setState 和 this.setState:
- 函數(shù)組件: 使用 useReducer 來管理復(fù)雜狀態(tài)邏輯。
- 類組件: 可以使用 setState 或 this.setState,但 useReducer 更適合處理復(fù)雜狀態(tài)邏輯。
5.useCallback - shouldComponentUpdate:
- 函數(shù)組件: 使用
useCallback來記憶回調(diào)函數(shù),以防止每次重新渲染時(shí)重新創(chuàng)建它。 - 類組件: 在
shouldComponentUpdate中進(jìn)行優(yōu)化,防止不必要的渲染。
6.useMemo - shouldComponentUpdate:
- 函數(shù)組件: 使用
useMemo來記憶計(jì)算昂貴的計(jì)算結(jié)果。 - 類組件: 在
shouldComponentUpdate中進(jìn)行優(yōu)化,防止不必要的渲染。
這些是一些常見的 Hooks,它們?yōu)楹瘮?shù)組件提供了類似于類組件生命周期方法的功能。使用 Hooks 可以更清晰地組織和重用邏輯。需要注意的是,使用 Hooks 時(shí),每個(gè) Hook 都是相互獨(dú)立的,而類組件中的生命周期方法可能會(huì)涵蓋多個(gè)生命周期階段。
2.1 useState
useState 是 React Hooks 中用于在函數(shù)組件中添加狀態(tài)的關(guān)鍵之一。它允許你在函數(shù)組件中添加和管理狀態(tài),而不需要使用類組件。
useState 返回一個(gè)數(shù)組,其中包含兩個(gè)元素:當(dāng)前狀態(tài)的值和一個(gè)更新狀態(tài)的函數(shù)。
下面是 useState 的基本用法:
import React, { useState } from 'react';
function MyComponent() {
// 使用 useState 定義一個(gè)狀態(tài)變量,初始值為 'initialValue'
const [state, setState] = useState('initialValue');
return (
<div>
<p>Current State: {state}</p>
{/* 使用 setState 函數(shù)來更新狀態(tài) */}
<button onClick={() => setState('newValue')}>
Update State
</button>
</div>
);
}
export default MyComponent;在上面的例子中,useState 被調(diào)用并傳入初始狀態(tài) 'initialValue',返回的數(shù)組包含當(dāng)前狀態(tài)值 state 和更新狀態(tài)的函數(shù) setState。通過點(diǎn)擊按鈕,可以觸發(fā) setState 函數(shù)來更新狀態(tài)。
useState 的基本用法包括:
- 定義狀態(tài): 調(diào)用 useState 來聲明一個(gè)狀態(tài)變量,并傳入初始值。
- 獲取當(dāng)前狀態(tài)值: 使用返回的數(shù)組的第一個(gè)元素(例如,state)來獲取當(dāng)前狀態(tài)的值。
- 更新狀態(tài): 使用返回的數(shù)組的第二個(gè)元素(例如,setState)來更新狀態(tài)。setState 函數(shù)接受新的狀態(tài)值作為參數(shù)。
請(qǐng)注意,useState 可以在組件中多次調(diào)用,以添加多個(gè)狀態(tài)變量。每個(gè)狀態(tài)變量都有自己獨(dú)立的 setState 函數(shù)。
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment Count
</button>
<p>Text: {text}</p>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
</div>
);
}
export default MyComponent;在上面的例子中,MyComponent 組件有兩個(gè)狀態(tài)變量 count 和 text,每個(gè)都有自己的 setState 函數(shù)。
2.2 useEffect
useEffect 是 React Hooks 中用于處理副作用的關(guān)鍵之一。它在函數(shù)組件中提供了執(zhí)行副作用的能力。useEffect 接受兩個(gè)參數(shù):
- 一個(gè)函數(shù),包含需要執(zhí)行的副作用代碼。
- 一個(gè)可選的依賴數(shù)組,用于指定在依賴項(xiàng)發(fā)生變化時(shí)才重新運(yùn)行 useEffect。
import React, { useEffect } from 'react';
function MyComponent() {
// 在組件掛載后執(zhí)行一次
useEffect(() => {
// 執(zhí)行副作用的代碼
// 清理函數(shù)(componentWillUnmount 的替代)
return () => {
// 在組件卸載前執(zhí)行清理邏輯
};
}, [dependencies]); // 依賴項(xiàng)數(shù)組
return (
// 組件的 JSX
);
}
export default MyComponent;- Effect 函數(shù): 第一個(gè)參數(shù)是一個(gè)函數(shù),包含需要在每次渲染后執(zhí)行的副作用代碼。這個(gè)函數(shù)可以返回一個(gè)清理函數(shù)(cleanup function),用于在組件卸載時(shí)執(zhí)行清理邏輯,類似于 componentWillUnmount。
- 依賴項(xiàng)數(shù)組: 第二個(gè)參數(shù)是一個(gè)數(shù)組,包含影響副作用執(zhí)行的變量。如果依賴項(xiàng)數(shù)組中的任何一個(gè)變量發(fā)生變化,
useEffect就會(huì)重新運(yùn)行。如果省略依賴項(xiàng)數(shù)組,副作用將在每次組件渲染時(shí)都運(yùn)行。
以下是一些 useEffect 的常見用法:
- 只在組件掛載時(shí)執(zhí)行副作用:
useEffect(() => {
// 執(zhí)行副作用的代碼
return () => {
// 在組件卸載前執(zhí)行清理邏輯
};
}, []);- 在特定依賴項(xiàng)變化時(shí)執(zhí)行副作用:
useEffect(() => {
// 執(zhí)行副作用的代碼
return () => {
// 在特定依賴項(xiàng)變化時(shí)執(zhí)行清理邏輯
};
}, [dependency1, dependency2]);- 執(zhí)行異步操作:
useEffect(() => {
const fetchData = async () => {
try {
// 異步操作,比如從 API 獲取數(shù)據(jù)
const result = await fetchDataFromApi();
// 處理結(jié)果
} catch (error) {
// 處理錯(cuò)誤
}
};
fetchData();
return () => {
// 在組件卸載前執(zhí)行清理邏輯
};
}, [dependency]);useEffect 的使用取決于具體的需求,可以根據(jù)需要執(zhí)行副作用,并確保在組件卸載前進(jìn)行必要的清理。
2.3 useContext
useContext 是 React Hooks 中用于訪問 React 上下文的鉤子。它允許你在函數(shù)組件中訂閱 React 上下文的值,而無需使用 Context.Consumer。
下面是 useContext 的基本用法:
- 創(chuàng)建上下文: 使用
React.createContext創(chuàng)建一個(gè)上下文對(duì)象。 - 在頂層組件提供上下文的值: 使用
Context.Provider在組件樹的某個(gè)位置提供上下文的值。 - 在子組件中使用
useContext: 在需要訪問上下文的子組件中使用useContext來獲取上下文的值。
以下是一個(gè)簡單的例子:
import React, { createContext, useContext } from 'react';
// 創(chuàng)建一個(gè)上下文對(duì)象
const MyContext = createContext();
// 在頂層組件提供上下文的值
function MyProvider({ children }) {
const contextValue = 'Hello from Context';
return (
<MyContext.Provider value={contextValue}>
{children}
</MyContext.Provider>
);
}
// 在子組件中使用 useContext 獲取上下文的值
function MyComponent() {
const contextValue = useContext(MyContext);
return <p>{contextValue}</p>;
}
// 在應(yīng)用的頂層組件中使用 MyProvider 包裹子組件
function App() {
return (
<MyProvider>
<MyComponent />
</MyProvider>
);
}
export default App;如果組件分別在不同的組件中, 則可以定義一個(gè)文件導(dǎo)出定義的 context:
import { createContext } from 'react';
const MyContext = createContext();
export default MyContext;2.4 useReducer
useReducer 是 React Hooks 中用于管理復(fù)雜狀態(tài)邏輯的鉤子。它提供了一種可預(yù)測(cè)的方式來更新狀態(tài),尤其適用于處理具有多個(gè)可能操作的狀態(tài)。使用 useReducer 時(shí),你需要定義一個(gè) reducer 函數(shù),該函數(shù)負(fù)責(zé)處理不同的操作,并返回新的狀態(tài)。
下面是 useReducer 的基本用法:
- 定義 reducer 函數(shù): 創(chuàng)建一個(gè)接受當(dāng)前狀態(tài)和操作的函數(shù),根據(jù)操作類型返回新的狀態(tài)。reducer 函數(shù)的格式為
(state, action) => newState。 - 使用
useReducer: 在組件中調(diào)用useReducer并傳入 reducer 函數(shù)和初始狀態(tài)。 - 得到當(dāng)前狀態(tài)和 dispatch 函數(shù):
useReducer返回一個(gè)包含當(dāng)前狀態(tài)和 dispatch 函數(shù)的數(shù)組。 - dispatch 操作: 調(diào)用 dispatch 函數(shù)并傳入一個(gè)操作對(duì)象,reducer 將根據(jù)操作類型來更新狀態(tài)。
以下是一個(gè)簡單的例子:
import React, { useReducer } from 'react';
// 定義 reducer 函數(shù)
const reducer = (state, action) => {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
};
// 使用 useReducer
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
</div>
);
}
export default Counter;在上面的例子中,reducer 函數(shù)接收當(dāng)前狀態(tài)和操作,根據(jù)操作類型更新狀態(tài)。useReducer 返回一個(gè)包含當(dāng)前狀態(tài)和 dispatch 函數(shù)的數(shù)組。通過調(diào)用 dispatch 函數(shù),并傳入包含 type 屬性的操作對(duì)象,可以觸發(fā) reducer 來更新狀態(tài)。
useReducer 還支持傳入一個(gè)可選的初始化函數(shù),用于計(jì)算初始狀態(tài),例如:
const initialState = { count: 0 };
const init = (initialState) => {
return { count: initialState.count * 2 };
};
const [state, dispatch] = useReducer(reducer, initialState, init);在這個(gè)例子中,init 函數(shù)接收初始狀態(tài),并返回實(shí)際的初始狀態(tài)。這可以是有用的,例如在初始狀態(tài)需要基于某些計(jì)算的情況下。
使用 useReducer 的主要優(yōu)勢(shì)在于它使得狀態(tài)邏輯更加模塊化,特別是當(dāng)有多個(gè)操作可能影響狀態(tài)時(shí)。
2.5 useCallback
useCallback 是 React Hooks 中用于記憶回調(diào)函數(shù)的鉤子。它的主要作用是在依賴不變的情況下,返回一個(gè)記憶化的回調(diào)函數(shù),避免在每次渲染時(shí)創(chuàng)建新的回調(diào)函數(shù)。這有助于優(yōu)化性能,特別是在子組件中使用時(shí)。
基本的使用方式如下:
import React, { useCallback } from 'react';
function MyComponent({ onClick }) {
// 使用 useCallback 包裹回調(diào)函數(shù)
const memoizedCallback = useCallback(
() => {
// 回調(diào)函數(shù)的邏輯
console.log('Callback executed!');
},
// 依賴項(xiàng)數(shù)組
[/* dependencies */]
);
return (
<button onClick={memoizedCallback}>
Click me
</button>
);
}
export default MyComponent;在上面的例子中,useCallback 接收兩個(gè)參數(shù):一個(gè)回調(diào)函數(shù)和一個(gè)依賴項(xiàng)數(shù)組。它返回一個(gè)記憶化后的回調(diào)函數(shù) memoizedCallback。如果依賴項(xiàng)數(shù)組中的值沒有發(fā)生變化,memoizedCallback 將保持相同的引用,從而避免在每次渲染時(shí)重新創(chuàng)建回調(diào)函數(shù)。
常見的用法包括:
- 避免子組件的不必要渲染: 在將回調(diào)函數(shù)傳遞給子組件時(shí),使用
useCallback避免子組件不必要地重新渲染。
const memoizedCallback = useCallback(
() => {
// 回調(diào)函數(shù)的邏輯
},
[/* dependencies */]
);
return <ChildComponent onClick={memoizedCallback} />;- 作為依賴項(xiàng)傳遞給其他 Hook: 在使用其他 Hook 時(shí),將
useCallback的記憶化回調(diào)函數(shù)作為依賴項(xiàng)傳遞。
useEffect(() => {
// 使用 memoizedCallback 作為依賴項(xiàng)
someHook(memoizedCallback);
}, [memoizedCallback]);- 避免在依賴項(xiàng)變化時(shí)觸發(fā) effect: 在使用
useEffect時(shí),通過使用useCallback避免在依賴項(xiàng)變化時(shí)觸發(fā) effect。
useEffect(() => {
// 在 memoizedCallback 變化時(shí)執(zhí)行 effect
}, [memoizedCallback]);需要注意的是,過度使用 useCallback 可能會(huì)導(dǎo)致性能問題,因?yàn)槊總€(gè)記憶化的回調(diào)函數(shù)都需要額外的內(nèi)存。因此,只在確實(shí)有性能問題或需要時(shí)使用 useCallback。
2.6 useMemo
useMemo 是 React Hooks 中用于記憶化計(jì)算結(jié)果的鉤子。它接受一個(gè)計(jì)算函數(shù)和依賴項(xiàng)數(shù)組,并返回計(jì)算結(jié)果的記憶化版本。這有助于避免在每次渲染時(shí)重新計(jì)算耗時(shí)的操作,提高性能。
基本的使用方式如下:
import React, { useMemo } from 'react';
function MyComponent({ data }) {
// 使用 useMemo 記憶化計(jì)算結(jié)果
const memoizedResult = useMemo(
() => {
// 計(jì)算結(jié)果的邏輯
console.log('Computing result...');
return data.filter(item => item > 5);
},
// 依賴項(xiàng)數(shù)組
[data]
);
return (
<div>
<p>Result: {memoizedResult}</p>
</div>
);
}
export default MyComponent;在上面的例子中,useMemo 接收兩個(gè)參數(shù):一個(gè)計(jì)算函數(shù)和一個(gè)依賴項(xiàng)數(shù)組。它返回一個(gè)記憶化后的計(jì)算結(jié)果 memoizedResult。如果依賴項(xiàng)數(shù)組中的值沒有發(fā)生變化,memoizedResult 將保持相同的引用,從而避免在每次渲染時(shí)重新計(jì)算結(jié)果。
常見的用法包括:
- 優(yōu)化渲染性能: 避免在每次渲染時(shí)都執(zhí)行昂貴的計(jì)算,只在依賴項(xiàng)變化時(shí)重新計(jì)算。
const memoizedResult = useMemo(
() => {
// 昂貴的計(jì)算邏輯
},
[/* dependencies */]
);- 記憶化函數(shù): 當(dāng)需要在每次渲染時(shí)都返回一個(gè)新的函數(shù),但只有在依賴項(xiàng)變化時(shí)才創(chuàng)建新函數(shù)時(shí),可以使用
useMemo記憶化函數(shù)。
const memoizedFunction = useMemo(
() => {
return () => {
// 函數(shù)的邏輯
};
},
[/* dependencies */]
);- 避免重復(fù)計(jì)算: 當(dāng)某個(gè)計(jì)算結(jié)果僅在特定依賴項(xiàng)變化時(shí)才發(fā)生變化時(shí),使用
useMemo避免重復(fù)計(jì)算。
const memoizedResult = useMemo(
() => {
// 僅在特定依賴項(xiàng)變化時(shí)才計(jì)算結(jié)果
},
[specificDependency]
);需要注意的是,過度使用 useMemo 可能會(huì)導(dǎo)致性能問題,因?yàn)槊總€(gè)記憶化的結(jié)果都需要額外的內(nèi)存。因此,只在確實(shí)有性能問題或需要時(shí)使用 useMemo。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
React中g(shù)etDefaultProps的使用小結(jié)
React中的getDefaultProps功能允許開發(fā)者為類組件定義默認(rèn)屬性,提高組件的靈活性和容錯(cuò)性,本文介紹了getDefaultProps的作用、語法以及最佳實(shí)踐,并探討了其他替代方案,如函數(shù)組件中的默認(rèn)參數(shù)、高階組件和ContextAPI等,理解這些概念有助于提升代碼的可維護(hù)性和用戶體驗(yàn)2024-09-09
React中使用Workbox進(jìn)行預(yù)緩存的實(shí)現(xiàn)代碼
Workbox是Google Chrome團(tuán)隊(duì)推出的一套 PWA 的解決方案,這套解決方案當(dāng)中包含了核心庫和構(gòu)建工具,因此我們可以利用Workbox實(shí)現(xiàn)Service Worker的快速開發(fā),本文小編給大家介紹了React中使用Workbox進(jìn)行預(yù)緩存的實(shí)現(xiàn),需要的朋友可以參考下2023-11-11
React?Hooks中?useRef和useImperativeHandle的使用方式
這篇文章主要介紹了React?Hooks中?useRef和useImperativeHandle的使用方式,文中說明了useRef和useCallback一起使用,?可以解決閉包陷阱的問題,本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
TypeScript在React項(xiàng)目中的使用實(shí)踐總結(jié)
這篇文章主要介紹了TypeScript在React項(xiàng)目中的使用總結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
react native實(shí)現(xiàn)監(jiān)控手勢(shì)上下拉動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了react native實(shí)現(xiàn)監(jiān)控手勢(shì)上下拉動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
使用React18和WebSocket構(gòu)建實(shí)時(shí)通信功能詳解
WebSocket是一種在Web應(yīng)用中實(shí)現(xiàn)雙向通信的協(xié)議,它允許服務(wù)器主動(dòng)向客戶端推送數(shù)據(jù),而不需要客戶端發(fā)起請(qǐng)求,本文將探索如何在React?18應(yīng)用中使用WebSocket來實(shí)現(xiàn)實(shí)時(shí)通信,感興趣的可以了解下2024-01-01

