React Native從類組件到函數(shù)組件詳解
1. 發(fā)展趨勢(shì)
React Native社區(qū)中的趨勢(shì)是朝向使用函數(shù)組件(Functional Components)和Hooks的方向發(fā)展,而不是使用類組件(Class Components)。
React Native自推出Hooks API以來(lái),函數(shù)組件和Hooks的使用變得更加普遍和推薦。Hooks提供了更簡(jiǎn)潔、可讀性更高的代碼,并且在狀態(tài)管理、生命周期等方面提供了更強(qiáng)大的功能。使用Hooks可以更容易地共享邏輯和狀態(tài)邏輯,而無(wú)需使用類組件的復(fù)雜結(jié)構(gòu)。
以下是一些關(guān)于為什么React Native社區(qū)更傾向于使用函數(shù)組件和Hooks的理由:
- 可讀性和簡(jiǎn)潔性: 函數(shù)組件通常比類組件更短,更易于閱讀和理解。Hooks的引入使得在函數(shù)組件中管理狀態(tài)和副作用變得更為直觀。
- 邏輯復(fù)用: Hooks使得邏輯的復(fù)用更加容易。你可以使用自定義Hooks將組件之間的邏輯進(jìn)行抽象和共享,而不需要使用高階組件或渲染屬性。
- 更直觀的副作用處理: 使用useEffect等Hooks來(lái)處理副作用相對(duì)于類組件中的生命周期方法更為直觀。
- 更容易集成現(xiàn)代JavaScript特性: 使用函數(shù)組件和Hooks可以更容易地與ES6+和TypeScript等現(xiàn)代JavaScript特性集成。
- 更好的性能優(yōu)化: Hooks使得React能夠更好地進(jìn)行性能優(yōu)化,并且React Native的未來(lái)版本也更加注重性能。
2. Hooks vs Class
Hooks 提供了在函數(shù)組件中執(zhí)行副作用和訪問(wèn)狀態(tài)的能力。
下面是一些常見的 Hooks 及其在類組件中對(duì)應(yīng)的生命周期方法:
1.useState - setState:
- 函數(shù)組件: 使用 useState 來(lái)聲明和更新狀態(tài)。
- 類組件: 使用 this.setState 來(lái)更新狀態(tài)。
2.useEffect - componentDidMount, componentDidUpdate, componentWillUnmount:
函數(shù)組件: 使用 useEffect 來(lái)執(zhí)行副作用,可以模擬生命周期方法的行為。
類組件:
componentDidMount: 在組件掛載后調(diào)用。componentDidUpdate: 在組件更新后調(diào)用。componentWillUnmount: 在組件卸載前調(diào)用。
useEffect(() => {
// componentDidMount 和 componentDidUpdate 的邏輯
return () => {
// componentWillUnmount 的邏輯
};
}, [dependencies]);3.useContext - contextType:
- 函數(shù)組件:使用 useContext 來(lái)訪問(wèn) React 上下文。
- 類組件:使用 contextType 來(lái)訪問(wèn) React 上下文。
4.useReducer - setState 和 this.setState:
- 函數(shù)組件: 使用 useReducer 來(lái)管理復(fù)雜狀態(tài)邏輯。
- 類組件: 可以使用 setState 或 this.setState,但 useReducer 更適合處理復(fù)雜狀態(tài)邏輯。
5.useCallback - shouldComponentUpdate:
- 函數(shù)組件: 使用
useCallback來(lái)記憶回調(diào)函數(shù),以防止每次重新渲染時(shí)重新創(chuàng)建它。 - 類組件: 在
shouldComponentUpdate中進(jìn)行優(yōu)化,防止不必要的渲染。
6.useMemo - shouldComponentUpdate:
- 函數(shù)組件: 使用
useMemo來(lái)記憶計(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ù)來(lái)更新狀態(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。通過(guò)點(diǎn)擊按鈕,可以觸發(fā) setState 函數(shù)來(lái)更新狀態(tài)。
useState 的基本用法包括:
- 定義狀態(tài): 調(diào)用 useState 來(lái)聲明一個(gè)狀態(tài)變量,并傳入初始值。
- 獲取當(dāng)前狀態(tài)值: 使用返回的數(shù)組的第一個(gè)元素(例如,state)來(lái)獲取當(dāng)前狀態(tài)的值。
- 更新狀態(tài): 使用返回的數(shù)組的第二個(gè)元素(例如,setState)來(lái)更新狀態(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 中用于訪問(wèn) React 上下文的鉤子。它允許你在函數(shù)組件中訂閱 React 上下文的值,而無(wú)需使用 Context.Consumer。
下面是 useContext 的基本用法:
- 創(chuàng)建上下文: 使用
React.createContext創(chuàng)建一個(gè)上下文對(duì)象。 - 在頂層組件提供上下文的值: 使用
Context.Provider在組件樹的某個(gè)位置提供上下文的值。 - 在子組件中使用
useContext: 在需要訪問(wèn)上下文的子組件中使用useContext來(lái)獲取上下文的值。
以下是一個(gè)簡(jiǎn)單的例子:
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è)的方式來(lái)更新狀態(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ù)操作類型來(lái)更新狀態(tài)。
以下是一個(gè)簡(jiǎn)單的例子:
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ù)組。通過(guò)調(diào)用 dispatch 函數(shù),并傳入包含 type 屬性的操作對(duì)象,可以觸發(fā) reducer 來(lái)更新狀態(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ù)組中的值沒(méi)有發(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í),通過(guò)使用useCallback避免在依賴項(xiàng)變化時(shí)觸發(fā) effect。
useEffect(() => {
// 在 memoizedCallback 變化時(shí)執(zhí)行 effect
}, [memoizedCallback]);需要注意的是,過(guò)度使用 useCallback 可能會(huì)導(dǎo)致性能問(wèn)題,因?yàn)槊總€(gè)記憶化的回調(diào)函數(shù)都需要額外的內(nèi)存。因此,只在確實(shí)有性能問(wèn)題或需要時(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ù)組中的值沒(méi)有發(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]
);需要注意的是,過(guò)度使用 useMemo 可能會(huì)導(dǎo)致性能問(wèn)題,因?yàn)槊總€(gè)記憶化的結(jié)果都需要額外的內(nèi)存。因此,只在確實(shí)有性能問(wèn)題或需要時(shí)使用 useMemo。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
react?+?vite?+?ts項(xiàng)目中優(yōu)雅使用.svg文件
這篇文章主要為大家介紹了react?+?vite?+?ts項(xiàng)目中優(yōu)雅使用.svg文件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
解決React報(bào)錯(cuò)`value` prop on `input` should&
這篇文章主要為大家介紹了React報(bào)錯(cuò)`value` prop on `input` should not be null解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
React移動(dòng)端項(xiàng)目之pdf預(yù)覽問(wèn)題
這篇文章主要介紹了React移動(dòng)端項(xiàng)目之pdf預(yù)覽問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
react實(shí)現(xiàn)一個(gè)優(yōu)雅的圖片占位模塊組件詳解
這篇文章主要給大家介紹了關(guān)于react如何實(shí)現(xiàn)一個(gè)還算優(yōu)雅的占位模塊圖片組件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10
React超詳細(xì)分析useState與useReducer源碼
我正在處理的組件是表單的時(shí)間輸入。表單相對(duì)復(fù)雜,并且是動(dòng)態(tài)生成的,根據(jù)嵌套在其他數(shù)據(jù)中的數(shù)據(jù)顯示不同的字段。我正在用useReducer管理表單的狀態(tài),到目前為止效果很好2022-11-11
全棧輕量級(jí)搭配之Remix Prisma Sqlite使用分析
這篇文章主要為大家介紹了全棧輕量級(jí)搭配之Remix Prisma Sqlite使用示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05

