簡(jiǎn)介
在面試 React 前端開(kāi)發(fā)人員職位時(shí),為技術(shù)問(wèn)題做好充分準(zhǔn)備至關(guān)重要。React 已經(jīng)成為構(gòu)建用戶(hù)界面最流行的 JavaScript 庫(kù)之一,雇主通常注重評(píng)估候選人對(duì) React 核心概念、最佳實(shí)踐和相關(guān)技術(shù)的理解。在本文中,我們將探討 React 前端開(kāi)發(fā)人員面試期間常見(jiàn)問(wèn)題的完整列表。通過(guò)熟悉這些問(wèn)題及其答案,您可以增加成功的機(jī)會(huì)并展示您在 React 開(kāi)發(fā)方面的熟練程度。因此,讓我們深入探討您應(yīng)該準(zhǔn)備好在 React 前端開(kāi)發(fā)人員面試中解決的關(guān)鍵主題。
1.你知道哪些React hooks?
useState:用于管理功能組件中的狀態(tài)。
useEffect:用于在功能組件中執(zhí)行副作用,例如獲取數(shù)據(jù)或訂閱事件。
useContext:用于訪(fǎng)問(wèn)功能組件內(nèi)的 React 上下文的值。
useRef:用于創(chuàng)建對(duì)跨渲染持續(xù)存在的元素或值的可變引用。
useCallback:用于記憶函數(shù)以防止不必要的重新渲染。
useMemo:用于記憶值,通過(guò)緩存昂貴的計(jì)算來(lái)提高性能。
useReducer:用于通過(guò)reducer函數(shù)管理狀態(tài),類(lèi)似于Redux的工作原理。
useLayoutEffect:與useEffect類(lèi)似,但效果在所有DOM突變后同步運(yùn)行。
這些鉤子提供了強(qiáng)大的工具來(lái)管理狀態(tài)、處理副作用以及重用 React 功能組件中的邏輯。
了解更多(https://react.dev/reference/react)
2.什么是虛擬DOM?
虛擬 DOM 是 React 中的一個(gè)概念,其中創(chuàng)建實(shí)際 DOM(文檔對(duì)象模型)的輕量級(jí)虛擬表示并將其存儲(chǔ)在內(nèi)存中。它是一種用于優(yōu)化 Web 應(yīng)用程序性能的編程技術(shù)。
當(dāng) React 組件的數(shù)據(jù)或狀態(tài)發(fā)生更改時(shí),虛擬 DOM 會(huì)被更新,而不是直接操作真實(shí) DOM。然后,虛擬 DOM 計(jì)算組件的先前狀態(tài)和更新?tīng)顟B(tài)之間的差異,稱(chēng)為“比較”過(guò)程。
一旦識(shí)別出差異,React 就會(huì)高效地僅更新真實(shí) DOM 的必要部分以反映更改。這種方法最大限度地減少了實(shí)際 DOM 操作的數(shù)量,并提高了應(yīng)用程序的整體性能。
通過(guò)使用虛擬 DOM,React 提供了一種創(chuàng)建動(dòng)態(tài)和交互式用戶(hù)界面的方法,同時(shí)確保最佳效率和渲染速度。
3. 如何渲染元素?cái)?shù)組?
要渲染元素?cái)?shù)組,您可以使用該map()方法迭代該數(shù)組并返回一個(gè)新的 React 元素?cái)?shù)組。
const languages = [ "JavaScript", "TypeScript", "Python", ]; function App() { return ( <div> <ul>{languages.map((language) => <li>{language}</li>)}</ul> </div> ); }
了解更多(https://react.dev/learn/rendering-lists)
4. 受控組件和非受控組件有什么區(qū)別?
受控組件和非受控組件之間的區(qū)別在于它們?nèi)绾喂芾砗透缕錉顟B(tài)。
受控組件是狀態(tài)由 React 控制的組件。組件接收其當(dāng)前值并通過(guò) props 更新它。當(dāng)值改變時(shí)它也會(huì)觸發(fā)回調(diào)函數(shù)。這意味著該組件不存儲(chǔ)其自己的內(nèi)部狀態(tài)。相反,父組件管理該值并將其傳遞給受控組件。
import { useState } from 'react'; function App() { const [value, setValue] = useState(''); return ( <div> <h3>Controlled Component</h3> <input name="name" value={name} onChange={(e) => setValue(e.target.value)} /> <button onClick={() => console.log(value)}>Get Value</button> </div> ); }
另一方面,不受控制的組件使用 refs 或其他方法在內(nèi)部管理自己的狀態(tài)。它們獨(dú)立存儲(chǔ)和更新?tīng)顟B(tài),不依賴(lài) props 或回調(diào)。父組件對(duì)不受控組件的狀態(tài)控制較少。
import { useRef } from 'react'; function App() { const inputRef = useRef(null); return ( <div className="App"> <h3>Uncontrolled Component</h3> <input type="text" name="name" ref={inputRef} /> <button onClick={() => console.log(inputRef.current.value)}>Get Value</button> </div> ); }
了解更多(https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components)
5. 基于類(lèi)的 React 組件和函數(shù)式 React 組件有什么區(qū)別?
基于類(lèi)的組件和函數(shù)組件之間的主要區(qū)別在于它們的定義方式和使用的語(yǔ)法。
基于類(lèi)的組件被定義為 ES6 類(lèi)并擴(kuò)展該類(lèi)React.Component。他們使用該render方法返回定義組件輸出的 JSX (JavaScript XML)。this.state類(lèi)組件可以通過(guò)和訪(fǎng)問(wèn)組件生命周期方法和狀態(tài)管理this.setState()。
class App extends React.Component { state = { value: 0, }; handleAgeChange = () => { this.setState({ value: this.state.value + 1 }); }; render() { return ( <> <p>Value is {this.state.value}</p> <button onClick={this.handleAgeChange}> Increment value </button> </> ); } }
另一方面,函數(shù)組件被定義為簡(jiǎn)單的 JavaScript 函數(shù)。他們接受 props 作為參數(shù)并直接返回 JSX。功能組件無(wú)權(quán)訪(fǎng)問(wèn)生命周期方法或狀態(tài)。然而,隨著 React 16.8 中 React Hooks 的引入,功能組件現(xiàn)在可以管理狀態(tài)并使用其他功能,例如上下文和效果。
import { useState } from 'react'; const App = () => { const [value, setValue] = useState(0); const handleAgeChange = () => { setValue(value + 1); }; return ( <> <p>Value is {value}</p> <button onClick={handleAgeChange}> Increment value </button> </> ); }
一般來(lái)說(shuō),功能組件被認(rèn)為更簡(jiǎn)單、更容易閱讀和測(cè)試。建議盡可能使用函數(shù)式組件,除非有特定需要基于類(lèi)的組件。
6. 組件的生命周期方法有哪些?
生命周期方法是一種掛鉤組件生命周期不同階段的方法,允許您在特定時(shí)間執(zhí)行特定代碼。
以下是主要生命周期方法的列表:
constructor:這是創(chuàng)建組件時(shí)調(diào)用的第一個(gè)方法。它用于初始化狀態(tài)和綁定事件處理程序。在功能組件中,您可以將useState鉤子用于類(lèi)似的目的。
render:該方法負(fù)責(zé)渲染 JSX 標(biāo)記并返回要在屏幕上顯示的內(nèi)容。
componentDidMount:組件在 DOM 中渲染后立即調(diào)用此方法。它通常用于初始化任務(wù),例如 API 調(diào)用或設(shè)置事件偵聽(tīng)器。
componentDidUpdate:當(dāng)組件的 props 或 state 改變時(shí)調(diào)用此方法。它允許您執(zhí)行副作用、根據(jù)更改更新組件或觸發(fā)其他 API 調(diào)用。
componentWillUnmount:在組件從 DOM 中刪除之前調(diào)用此方法。它用于清理在 中設(shè)置的任何資源componentDidMount,例如刪除事件偵聽(tīng)器或取消計(jì)時(shí)器。
一些生命周期方法,如componentWillMount、componentWillReceiveProps和componentWillUpdate,已被棄用或替換為替代方法或掛鉤。
至于“this”,它指的是類(lèi)組件的當(dāng)前實(shí)例。它允許您訪(fǎng)問(wèn)組件內(nèi)的屬性和方法。在函數(shù)式組件中,不使用“this”,因?yàn)楹瘮?shù)未綁定到特定實(shí)例。
7. 使用useState有什么特點(diǎn)?
useState返回一個(gè)狀態(tài)值和一個(gè)更新它的函數(shù)。
const [value, setValue] = useState('Some state');
在初始渲染期間,返回的狀態(tài)與作為第一個(gè)參數(shù)傳遞的值匹配。該setState函數(shù)用于更新?tīng)顟B(tài)。它采用新的狀態(tài)值作為參數(shù),并對(duì)組件的重新渲染進(jìn)行排隊(duì)。該setState函數(shù)還可以接受回調(diào)函數(shù)作為參數(shù),該函數(shù)將之前的狀態(tài)值作為參數(shù)。
了解更多(https://react.dev/reference/react/useState)
8. 使用useEffect有什么特點(diǎn)?
鉤子useEffect允許您在功能組件中執(zhí)行副作用。
稱(chēng)為 React 渲染階段的功能組件的主體內(nèi)部不允許出現(xiàn)突變、訂閱、計(jì)時(shí)器、日志記錄和其他副作用。這可能會(huì)導(dǎo)致用戶(hù)界面中出現(xiàn)令人困惑的錯(cuò)誤和不一致。
相反,建議使用 useEffect。傳遞給 useEffect 的函數(shù)將在渲染提交到屏幕后執(zhí)行,或者如果您傳遞一組依賴(lài)項(xiàng)作為第二個(gè)參數(shù),則每次依賴(lài)項(xiàng)之一發(fā)生更改時(shí)都會(huì)調(diào)用該函數(shù)。
useEffect(() => { console.log('Logging something'); }, [])
了解更多(https://react.dev/reference/react/useEffect)
9. 如何跟蹤功能組件的卸載?
通常,useEffect創(chuàng)建在組件離開(kāi)屏幕之前需要清理或重置的資源,例如訂閱或計(jì)時(shí)器標(biāo)識(shí)符。
為了做到這一點(diǎn),傳遞給的函數(shù)useEffect可以返回一個(gè)清理函數(shù)。清理函數(shù)在組件從用戶(hù)界面刪除之前運(yùn)行,以防止內(nèi)存泄漏。此外,如果組件渲染多次(通常是這種情況),則在執(zhí)行下一個(gè)效果之前會(huì)清除上一個(gè)效果。
useEffect(() => { function handleChange(value) { setValue(value); } SomeAPI.doFunction(id, handleChange); return function cleanup() { SomeAPI.undoFunction(id, handleChange); }; })
10. React 中的 props 是什么?
Props 是從父組件傳遞給組件的數(shù)據(jù)。道具
是只讀的,無(wú)法更改。
// Parent component const Parent = () => { const data = "Hello, World!"; return ( <div> <Child data={data} /> </div> ); }; // Child component const Child = ({ data }) => { return <div>{data}</div>; };
了解更多(https://react.dev/learn/passing-props-to-a-component)
11. 什么是狀態(tài)管理器?您曾與哪些狀態(tài)管理器共事過(guò)或認(rèn)識(shí)哪些狀態(tài)管理器?
狀態(tài)管理器是幫助管理應(yīng)用程序狀態(tài)的工具或庫(kù)。它提供了一個(gè)集中存儲(chǔ)或容器來(lái)存儲(chǔ)和管理可由應(yīng)用程序中的不同組件訪(fǎng)問(wèn)和更新的數(shù)據(jù)。
狀態(tài)管理器可以解決幾個(gè)問(wèn)題。首先,將數(shù)據(jù)和與其相關(guān)的邏輯與組件分離是一個(gè)很好的實(shí)踐。其次,當(dāng)使用本地狀態(tài)并在組件之間傳遞它時(shí),由于組件可能存在深層嵌套,代碼可能會(huì)變得復(fù)雜。通過(guò)擁有全局存儲(chǔ),我們可以訪(fǎng)問(wèn)和修改來(lái)自任何組件的數(shù)據(jù)。
除了 React Context,Redux 或 MobX 通常用作狀態(tài)管理庫(kù)。
了解更多(https://mobx.js.org/README.html)和(https://redux-toolkit.js.org/)
12. 在什么情況下可以使用本地狀態(tài),什么時(shí)候應(yīng)該使用全局狀態(tài)?
如果本地狀態(tài)僅在一個(gè)組件中使用并且不打算將其傳遞給其他組件,則建議使用本地狀態(tài)。本地狀態(tài)也用在表示列表中單個(gè)項(xiàng)目的組件中。但是,如果組件分解涉及嵌套組件且數(shù)據(jù)沿層次結(jié)構(gòu)傳遞,則最好使用全局狀態(tài)。
13. Redux中的reducer是什么,它有哪些參數(shù)?
減速器是一個(gè)以狀態(tài)和操作作為參數(shù)的純函數(shù)。在減速器內(nèi)部,我們跟蹤接收到的操作的類(lèi)型,并根據(jù)它修改狀態(tài)并返回一個(gè)新的狀態(tài)對(duì)象。
export default function appReducer(state = initialState, action) { // 減速器通常查看操作類(lèi)型字段來(lái)決定發(fā)生什么 switch (action.type) { // 根據(jù)不同類(lèi)型的操作在這里做一些事情 default: // 如果此減速器無(wú)法識(shí)別操作類(lèi)型,或者不 // 關(guān)心這個(gè)特定的動(dòng)作,返回現(xiàn)有狀態(tài)不變 return state } }
了解更多(https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers)
14. 什么是 Action,如何更改 Redux 中的狀態(tài)?
Action 是一個(gè)簡(jiǎn)單的 JavaScript 對(duì)象,必須有一個(gè)
類(lèi)型字段。
{ type: "SOME_TYPE" }
您還可以選擇添加一些數(shù)據(jù)作為有效負(fù)載。為了
改變狀態(tài),需要調(diào)用dispatch函數(shù),我們將
action傳遞給它
{ type: "SOME_TYPE", payload: "Any payload", }
了解更多(https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers)
15. Redux 實(shí)現(xiàn)了哪種模式?
Redux 實(shí)現(xiàn)了Flux 模式,它是應(yīng)用程序的可預(yù)測(cè)狀態(tài)管理模式。它通過(guò)引入單向數(shù)據(jù)流和應(yīng)用程序狀態(tài)的集中存儲(chǔ)來(lái)幫助管理應(yīng)用程序的狀態(tài)。
了解更多(https://www.newline.co/fullstack-react/30-days-of-react/day-18/#:~:text=Flux%20is%20a%20pattern%20for,default%20method%20for%20handling%20data.)
16. Mobx 實(shí)現(xiàn)哪種模式?
Mobx 實(shí)現(xiàn)了觀察者模式,也稱(chēng)為發(fā)布-訂閱模式。
了解更多(https://www.patterns.dev/posts/observer-pattern)
17. 使用 Mobx 的特點(diǎn)是什么?
Mobx 提供了類(lèi)似observable和的裝飾器computed來(lái)定義可觀察的狀態(tài)和反應(yīng)函數(shù)。用action修飾的動(dòng)作用于修改狀態(tài),確保跟蹤所有更改。Mobx 還提供自動(dòng)依賴(lài)跟蹤、不同類(lèi)型的反應(yīng)、對(duì)反應(yīng)性的細(xì)粒度控制,以及通過(guò) mobx-react 包與 React 無(wú)縫集成??傮w而言,Mobx 通過(guò)根據(jù)可觀察狀態(tài)的變化自動(dòng)執(zhí)行更新過(guò)程來(lái)簡(jiǎn)化狀態(tài)管理。
18. 如何訪(fǎng)問(wèn)Mobx狀態(tài)下的變量?
observable您可以通過(guò)使用裝飾器將變量定義為可觀察來(lái)訪(fǎng)問(wèn)狀態(tài)中的變量。這是一個(gè)例子:
import { observable, computed } from 'mobx'; class MyStore { @observable myVariable = 'Hello Mobx'; @computed get capitalizedVariable() { return this.myVariable.toUpperCase(); } } const store = new MyStore(); console.log(store.capitalizedVariable); // 輸出:HELLO MOBX store.myVariable = 'Hi Mobx'; console.log(store.capitalizedVariable); //輸出 : HI MOBX
在此示例中,myVariable被定義為使用裝飾器的可觀察對(duì)象observable。然后您可以使用訪(fǎng)問(wèn)該變量store.myVariable。所做的任何更改myVariable都會(huì)自動(dòng)觸發(fā)相關(guān)組件或反應(yīng)的更新。
了解更多(https://mobx.js.org/actions.html)
19.Redux和Mobx有什么區(qū)別?
Redux 是一個(gè)更簡(jiǎn)單、更固執(zhí)己見(jiàn)的狀態(tài)管理庫(kù),遵循嚴(yán)格的單向數(shù)據(jù)流并促進(jìn)不變性。它需要更多的樣板代碼和顯式更新,但與 React 具有出色的集成。
另一方面,Mobx 提供了更靈活、更直觀的 API,并且樣板代碼更少。它允許您直接修改狀態(tài)并自動(dòng)跟蹤更改以獲得更好的性能。Redux 和 Mobx 之間的選擇取決于您的具體需求和偏好。
20.什么是JSX?
默認(rèn)情況下,以下語(yǔ)法用于在 React 中創(chuàng)建元素。
const someElement = React.createElement( 'h3', {className: 'title__value'}, 'Some Title Value' );
但我們已經(jīng)習(xí)慣這樣看
const someElement = ( <h3 className='title__value'>Some Title Value</h3> );
這正是標(biāo)記所謂的 jsx。這是一種語(yǔ)言擴(kuò)展
,簡(jiǎn)化了代碼和開(kāi)發(fā)的感知 了解
更多(https://react.dev/learn/writing-markup-with-jsx#jsx-putting-markup-into-javascript)
21.什么是道具鉆探?
Props 鉆取是指通過(guò)多層嵌套組件傳遞 props 的過(guò)程,即使某些中間組件不直接使用這些 props。這可能會(huì)導(dǎo)致代碼結(jié)構(gòu)復(fù)雜且繁瑣。
// 父組件 const Parent = () => { const data = "Hello, World!"; return ( <div> <ChildA data={data} /> </div> ); }; // 中級(jí) ChildA 組建 const ChildA = ({ data }) => { return ( <div> <ChildB data={data} /> </div> ); }; // 葉 ChildB 組件 const ChildB = ({ data }) => { return <div>{data}</div>; };
在此示例中,dataprop 從 Parent 組件傳遞到 ChildA,然后從 ChildA 傳遞到 ChildB,即使 ChildA 不直接使用該 prop。當(dāng)存在許多級(jí)別的嵌套或當(dāng)組件樹(shù)中更靠下的組件需要訪(fǎng)問(wèn)數(shù)據(jù)時(shí),這可能會(huì)成為問(wèn)題。它會(huì)使代碼更難維護(hù)和理解。
可以通過(guò)使用其他模式(如上下文或狀態(tài)管理庫(kù)(如 Redux 或 MobX))來(lái)緩解 Props 鉆探。這些方法允許組件訪(fǎng)問(wèn)數(shù)據(jù),而不需要通過(guò)每個(gè)中間組件傳遞 props。
22. 如何有條件地渲染元素?
您可以使用任何條件運(yùn)算符,包括三元。
return ( <div> {isVisible && <span>I'm visible!</span>} </div> );
return ( <div> {isOnline ? <span>I'm online!</span> : <span>I'm offline</span>} </div> );
if (isOnline) { element = <span>I'm online!</span>; } else { element = <span>I'm offline</span>; } return ( <div> {element} </div> );
了解更多(https://react.dev/learn/conditional-rendering)
23. useMemo 的用途是什么?它是如何工作的?
useMemo用于緩存和記憶
計(jì)算結(jié)果。
傳遞創(chuàng)建函數(shù)和依賴(lài)項(xiàng)數(shù)組。useMemo僅當(dāng)任何依賴(lài)項(xiàng)的值發(fā)生更改時(shí),才會(huì)重新計(jì)算記憶值。這種優(yōu)化有助于避免
每次渲染時(shí)進(jìn)行昂貴的計(jì)算。
使用第一個(gè)參數(shù),該函數(shù)接受執(zhí)行計(jì)算的回調(diào),使用第二個(gè)依賴(lài)項(xiàng)數(shù)組,僅當(dāng)至少一個(gè)依賴(lài)項(xiàng)發(fā)生更改時(shí),該函數(shù)才會(huì)重新執(zhí)行計(jì)算。
const memoValue = useMemo(() => computeFunc(paramA, paramB), [paramA, paramB]);
了解更多(https://react.dev/reference/react/useMemo)
24. useCallback 的用途是什么?它是如何工作的?
該useCallback鉤子將返回回調(diào)的記憶版本,僅當(dāng)依賴(lài)項(xiàng)之一的值發(fā)生更改時(shí)該版本才會(huì)更改。
當(dāng)將回調(diào)傳遞給依賴(lài)鏈接相等性來(lái)防止不必要的渲染的優(yōu)化子組件時(shí),這非常有用。
const callbackValue = useCallback(() => computeFunc(paramA, paramB), [paramA, paramB]);
了解更多(https://react.dev/reference/react/useCallback)
25. useMemo 和 useCallback 有什么區(qū)別?
useMemo用于記憶計(jì)算結(jié)果,而useCallback用于記憶函數(shù)本身。
useMemo如果依賴(lài)項(xiàng)未更改,則緩存計(jì)算值并在后續(xù)渲染時(shí)返回該值。
useCallback緩存函數(shù)本身并返回相同的實(shí)例,除非依賴(lài)項(xiàng)已更改。
26.什么是React上下文?
React Context 是一項(xiàng)功能,它提供了一種通過(guò)組件樹(shù)傳遞數(shù)據(jù)的方法,而無(wú)需在每個(gè)級(jí)別手動(dòng)傳遞 props。它允許您創(chuàng)建一個(gè)全局狀態(tài),樹(shù)中的任何組件都可以訪(fǎng)問(wèn)該狀態(tài),無(wú)論其位置如何。當(dāng)您需要在未通過(guò) props 直接連接的多個(gè)組件之間共享數(shù)據(jù)時(shí),上下文非常有用。
React Context API 由三個(gè)主要部分組成:
createContext:該函數(shù)用于創(chuàng)建一個(gè)新的上下文對(duì)象。
Context.Provider:該組件用于向上下文提供值。它包裝了需要訪(fǎng)問(wèn)該值的組件。
Context.Consumer或useContext鉤子:該組件或鉤子用于消耗上下文中的值。它可以在上下文提供者內(nèi)的任何組件中使用。
通過(guò)使用 React Context,您可以避免道具鉆探(通過(guò)多個(gè)級(jí)別的組件傳遞道具)并輕松管理更高級(jí)別的狀態(tài),使您的代碼更有組織性和效率。
了解更多(https://react.dev/learn/passing-data-deeply-with-context)
27. useContext 的用途是什么?它是如何工作的?
在典型的 React 應(yīng)用程序中,數(shù)據(jù)使用 props 從上到下(從父組件到子組件)傳遞。然而,這樣的使用方法對(duì)于某些類(lèi)型的 props
(例如,選擇的語(yǔ)言、UI 主題)來(lái)說(shuō)可能過(guò)于繁瑣,必須將其傳遞給應(yīng)用程序中的許多組件。上下文提供了一種在組件之間共享此類(lèi)數(shù)據(jù)的方法,而無(wú)需通過(guò)
樹(shù)的每個(gè)級(jí)別顯式傳遞 props。 當(dāng)上下文值改變
時(shí),調(diào)用 useContext 的組件總是會(huì)重新渲染。
如果重新渲染組件的成本很高,您可以使用記憶來(lái)優(yōu)化它。
const App = () => { const theme = useContext(ThemeContext); return ( <div style={{ color: theme.palette.primary.main }}> Some div </div> ); }
了解更多(https://react.dev/reference/react/useContext)
28. useRef 的用途是什么?它是如何工作的?
useRef返回一個(gè)可修改的 ref 對(duì)象,一個(gè)屬性。其中的當(dāng)前值由傳遞的參數(shù)初始化。返回的對(duì)象將在組件的整個(gè)生命周期內(nèi)持續(xù)存在,并且不會(huì)因渲染而改變。
通常的用例是以命令式方式訪(fǎng)問(wèn)后代
。即使用 ref,我們可以顯式引用 DOM 元素。
const App = () => { const inputRef = useRef(null); const buttonClick = () => { inputRef.current.focus(); } return ( <> <input ref={inputRef} type="text" /> <button onClick={buttonClick}>Focus on input tag</button> </> ) }
了解更多(https://react.dev/reference/react/useRef)
29. 什么是React.memo()?
React.memo()是一個(gè)高階分量。如果您的組件始終使用不變的 props 渲染相同的內(nèi)容,則可以將其包裝在調(diào)用中React.memo()以在某些情況下提高性能,從而記住結(jié)果。這意味著 React 將使用上次渲染的結(jié)果,避免重新渲染。React.memo()只影響道具的變化。如果一個(gè)功能組件被包裝在 React.memo 中并使用 useState、useReducer 或 useContext,那么當(dāng)狀態(tài)或上下文發(fā)生變化時(shí),它將重新渲染。
import { memo } from 'react'; const MemoComponent = memo(MemoComponent = (props) => { // ... });
了解更多(https://react.dev/reference/react/memo)
30.什么是React Fragment?
從組件返回多個(gè)元素是 React 中的常見(jiàn)做法。片段允許您形成子元素列表,而無(wú)需在 DOM 中創(chuàng)建不必要的節(jié)點(diǎn)。
<> <OneChild /> <AnotherChild /> </> // or <React.Fragment> <OneChild /> <AnotherChild /> </React.Fragment>
了解更多(https://react.dev/reference/react/Fragment)
31.什么是React協(xié)調(diào)?
協(xié)調(diào)是一種 React 算法,用于區(qū)分一棵元素樹(shù)與另一棵元素樹(shù),以確定需要替換的部分。
協(xié)調(diào)是我們過(guò)去所說(shuō)的虛擬 DOM 背后的算法。這個(gè)定義聽(tīng)起來(lái)是這樣的:當(dāng)你渲染一個(gè) React 應(yīng)用程序時(shí),描述該應(yīng)用程序的元素樹(shù)是在保留的內(nèi)存中生成的。然后這棵樹(shù)被包含在渲染環(huán)境中——例如,瀏覽器應(yīng)用程序,它被翻譯成一組 DOM 操作。當(dāng)應(yīng)用程序狀態(tài)更新時(shí),會(huì)生成一棵新樹(shù)。將新樹(shù)與前一棵樹(shù)進(jìn)行比較,以便準(zhǔn)確計(jì)算并啟用重繪更新的應(yīng)用程序所需的操作。
了解更多(https://react.dev/learn/preserving-and-resetting-state)
32. 為什么使用map()時(shí)需要列表中的鍵?
這些鍵幫助 React 確定哪些元素已更改、
添加或刪除。必須指定它們,以便 React 可以
隨著時(shí)間的推移匹配數(shù)組元素。選擇鍵的最佳方法是使用能夠清楚區(qū)分列表項(xiàng)與其鄰居的字符串。大多數(shù)情況下,您將使用數(shù)據(jù)中的 ID 作為密鑰。
const languages = [ { id: 1, lang: "JavaScript", }, { id: 2, lang: "TypeScript", }, { id: 3, lang: "Python", }, ]; const App = () => { return ( <div> <ul>{languages.map((language) => ( <li key={`${language.id}_${language.lang}`}>{language.lang}</li> ))} </ul> </div> ); }
了解更多(https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)
33. 如何在 Redux Thunk 中處理異步操作?
要使用 Redux Thunk,您需要將其作為中間件導(dǎo)入。動(dòng)作創(chuàng)建者不僅應(yīng)該返回一個(gè)對(duì)象,還應(yīng)該返回一個(gè)以調(diào)度為參數(shù)的函數(shù)。
export const addUser = ({ firstName, lastName }) => { return dispatch => { dispatch(addUserStart()); } axios.post('https://jsonplaceholder.typicode.com/users', { firstName, lastName, completed: false }) .then(res => { dispatch(addUserSuccess(res.data)); }) .catch(error => { dispatch(addUserError(error.message)); }) }
了解更多(https://redux.js.org/usage/writing-logic-thunks)
34. 如何跟蹤功能組件中對(duì)象字段的變化?
為此,您需要使用掛鉤useEffect并將對(duì)象的字段作為依賴(lài)項(xiàng)數(shù)組傳遞。
useEffect(() => { console.log('Changed!') }, [obj.someField])
35.如何訪(fǎng)問(wèn)DOM元素?
引用是使用React.createRef()或useRef()鉤子創(chuàng)建的,并通過(guò) ref 屬性附加到 React 元素。通過(guò)訪(fǎng)問(wèn)創(chuàng)建的引用,我們可以使用ref.current.
const App = () => { const myRef = useRef(null); const handleClick = () => { console.log(myRef.current); // Accessing the DOM element }; return ( <div> <input type="text" ref={myRef} /> <button onClick={handleClick}>Click Me</button> </div> ); } export default App;
36.什么是自定義鉤子?
自定義鉤子是一個(gè)允許您在不同組件之間重用邏輯的功能。它是一種封裝可重用邏輯的方法,以便可以在多個(gè)組件之間輕松共享和重用。自定義掛鉤是通常以單詞 * use *開(kāi)頭的函數(shù),并且可以根據(jù)需要調(diào)用其他掛鉤。
了解更多(https://react.dev/learn/reusing-logic-with-custom-hooks)
37.什么是公共API?
在索引文件的上下文中,公共 API 通常是指向外部模塊或組件公開(kāi)并可訪(fǎng)問(wèn)的接口或函數(shù)。
以下是表示公共 API 的索引文件的代碼示例:
// index.js export function greet(name) { return `Hello, ${name}!`; } export function calculateSum(a, b) { return a + b; }
在此示例中,index.js 文件充當(dāng)公共 API,其中導(dǎo)出函數(shù)greet()和,并且可以通過(guò)導(dǎo)入函數(shù)從其他模塊訪(fǎng)問(wèn)它們。calculateSum()其他模塊可以導(dǎo)入并使用這些函數(shù)作為其實(shí)現(xiàn)的一部分:
// main.js import { greet, calculateSum } from './index.js'; console.log(greet('John')); // Hello, John! console.log(calculateSum(5, 3)); // 8
通過(guò)從索引文件導(dǎo)出特定函數(shù),我們定義了模塊的公共 API,允許其他模塊使用這些函數(shù)。
38. 創(chuàng)建自定義鉤子的規(guī)則是什么?
鉤子名稱(chēng)以“use”開(kāi)頭。
如果需要,請(qǐng)使用現(xiàn)有的掛鉤。
不要有條件地調(diào)用鉤子。
將可重用邏輯提取到自定義掛鉤中。
自定義鉤子必須是純函數(shù)。
自定義掛鉤可以返回值或其他掛鉤。
描述性地命名自定義掛鉤。 了解更多(https://react.dev/learn/reusing-logic-with-custom-hooks)
39.什么是SSR(服務(wù)器端渲染)?
服務(wù)器端渲染(SSR)是一種用于在服務(wù)器上渲染頁(yè)面并將完整渲染的頁(yè)面發(fā)送到客戶(hù)端進(jìn)行顯示的技術(shù)。它允許服務(wù)器生成網(wǎng)頁(yè)的完整 HTML 標(biāo)記(包括其動(dòng)態(tài)內(nèi)容),并將其作為對(duì)請(qǐng)求的響應(yīng)發(fā)送到客戶(hù)端。
在傳統(tǒng)的客戶(hù)端渲染方法中,客戶(hù)端接收最小的 HTML 頁(yè)面,然后向服務(wù)器發(fā)出額外的數(shù)據(jù)和資源請(qǐng)求,這些數(shù)據(jù)和資源用于在客戶(hù)端渲染頁(yè)面。這可能會(huì)導(dǎo)致初始頁(yè)面加載時(shí)間變慢,并對(duì)搜索引擎優(yōu)化 (SEO) 產(chǎn)生負(fù)面影響,因?yàn)樗阉饕媾老x(chóng)很難對(duì) JavaScript 驅(qū)動(dòng)的內(nèi)容建立索引。
通過(guò) SSR,服務(wù)器通過(guò)執(zhí)行必要的 JavaScript 代碼來(lái)生成最終的 HTML 來(lái)負(fù)責(zé)渲染網(wǎng)頁(yè)。這意味著客戶(hù)端從服務(wù)器接收完全呈現(xiàn)的頁(yè)面,從而減少了額外資源請(qǐng)求的需要。SSR 縮短了初始頁(yè)面加載時(shí)間,并允許搜索引擎輕松索引內(nèi)容,從而實(shí)現(xiàn)更好的 SEO。
SSR 通常用于框架和庫(kù)中,例如用于 React 的 Next.js 和用于 Vue.js 的 Nuxt.js,以啟用服務(wù)器端渲染功能。這些框架為您處理服務(wù)器端渲染邏輯,使實(shí)現(xiàn) SSR 變得更加容易。
40.使用SSR有什么好處?
改進(jìn)的初始加載時(shí)間:SSR 允許服務(wù)器將完全渲染的 HTML 頁(yè)面發(fā)送到客戶(hù)端,從而減少客戶(hù)端所需的處理量。這可以縮短初始加載時(shí)間,因?yàn)橛脩?hù)可以更快地看到完整的頁(yè)面。
SEO友好:搜索引擎可以有效地抓取和索引SSR頁(yè)面的內(nèi)容,因?yàn)橥耆秩镜腍TML在初始響應(yīng)中可用。這提高了搜索引擎的可見(jiàn)性并有助于更好的搜索排名。
可訪(fǎng)問(wèn)性:SSR 確保禁用 JavaScript 或使用輔助技術(shù)的用戶(hù)可以訪(fǎng)問(wèn)內(nèi)容。通過(guò)在服務(wù)器上生成 HTML,SSR 為所有用戶(hù)提供可靠且易于訪(fǎng)問(wèn)的用戶(hù)體驗(yàn)。
低帶寬環(huán)境下的性能:SSR減少了客戶(hù)端需要下載的數(shù)據(jù)量,對(duì)低帶寬或高延遲環(huán)境下的用戶(hù)有利。這對(duì)于移動(dòng)用戶(hù)或互聯(lián)網(wǎng)連接速度較慢的用戶(hù)尤其重要。
雖然 SSR 提供了這些優(yōu)勢(shì),但值得注意的是,與客戶(hù)端渲染方法相比,它可能會(huì)帶來(lái)更多的服務(wù)器負(fù)載和維護(hù)復(fù)雜性。應(yīng)仔細(xì)考慮緩存、可擴(kuò)展性和服務(wù)器端渲染性能優(yōu)化等因素。
41.你知道Next.js的主要功能有哪些?
1、getStaticProps:此方法用于在構(gòu)建時(shí)獲取數(shù)據(jù)并將頁(yè)面預(yù)渲染為靜態(tài) HTML。它確保數(shù)據(jù)在構(gòu)建時(shí)可用,并且不會(huì)因后續(xù)請(qǐng)求而更改。
export async function getStaticProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; }
2、getServerSideProps:該方法用于在每次請(qǐng)求時(shí)獲取數(shù)據(jù)并在服務(wù)器上預(yù)渲染頁(yè)面。當(dāng)您需要獲取可能經(jīng)常更改或特定于用戶(hù)的數(shù)據(jù)時(shí),可以使用它。
export async function getServerSideProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; }
3、getStaticPaths:此方法用于動(dòng)態(tài)路由中,以指定應(yīng)在構(gòu)建時(shí)預(yù)渲染的路徑列表。它通常用于獲取帶有參數(shù)的動(dòng)態(tài)路由的數(shù)據(jù)。
export async function getStaticPaths() { const res = await fetch('https://api.example.com/posts'); const posts = await res.json(); const paths = posts.map((post) => ({ params: { id: post.id } })); return { paths, fallback: false }; }
了解更多(https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating)
42.什么是短絨?
Linters 是用于檢查源代碼是否存在潛在錯(cuò)誤、錯(cuò)誤、風(fēng)格不一致和可維護(hù)性問(wèn)題的工具。它們幫助執(zhí)行編碼標(biāo)準(zhǔn)并確保整個(gè)代碼庫(kù)的代碼質(zhì)量和一致性。
Linters 的工作原理是掃描源代碼并將其與一組預(yù)定義的規(guī)則或指南進(jìn)行比較。這些規(guī)則可以包括語(yǔ)法和格式約定、最佳實(shí)踐、潛在錯(cuò)誤和代碼異味。當(dāng) linter 發(fā)現(xiàn)違反規(guī)則時(shí),它會(huì)生成警告或錯(cuò)誤,突出顯示需要注意的特定行或多行代碼。
使用 linter 可以帶來(lái)幾個(gè)好處:
代碼質(zhì)量:Linter 有助于識(shí)別和防止?jié)撛诘腻e(cuò)誤、代碼異味和反模式,從而提高代碼質(zhì)量。
一致性:Linter 強(qiáng)制執(zhí)行編碼約定和風(fēng)格指南,確保整個(gè)代碼庫(kù)的格式和代碼結(jié)構(gòu)一致,即使多個(gè)開(kāi)發(fā)人員正在處理同一個(gè)項(xiàng)目時(shí)也是如此。
可維護(hù)性:通過(guò)盡早發(fā)現(xiàn)問(wèn)題并促進(jìn)良好的編碼實(shí)踐,linter 有助于代碼的可維護(hù)性,使理解、修改和擴(kuò)展代碼庫(kù)變得更容易。
效率:Linter 可以通過(guò)自動(dòng)化代碼審查流程并在常見(jiàn)錯(cuò)誤在開(kāi)發(fā)或生產(chǎn)過(guò)程中引起問(wèn)題之前發(fā)現(xiàn)它們,從而節(jié)省開(kāi)發(fā)人員的時(shí)間。
一些流行的 linter 包括用于 JavaScript 的 ESLint 以及用于 CSS 和 Sass 的 Stylelint。
了解更多(https://eslint.org/docs/latest/use/getting-started)
43. 你知道哪些 React 架構(gòu)解決方案?
有多種用于構(gòu)建 React 項(xiàng)目的架構(gòu)解決方案和模式。一些受歡迎的包括:
MVC(模型-視圖-控制器):MVC 是一種傳統(tǒng)的架構(gòu)模式,它將應(yīng)用程序分為三個(gè)主要組件 - 模型、視圖和控制器。React 可以在 View 層中使用來(lái)渲染 UI,而其他庫(kù)或框架可以用于 Model 和 Controller 層。
Flux:Flux是Facebook專(zhuān)門(mén)針對(duì)React應(yīng)用程序推出的應(yīng)用程序架構(gòu)。它遵循單向數(shù)據(jù)流,其中數(shù)據(jù)沿單個(gè)方向流動(dòng),從而更容易理解和調(diào)試應(yīng)用程序的狀態(tài)更改。
原子設(shè)計(jì):原子設(shè)計(jì)并不是 React 特有的,而是一種將 UI 劃分為更小、可重用組件的設(shè)計(jì)方法。它鼓勵(lì)構(gòu)建小型、獨(dú)立且可以組合以創(chuàng)建更復(fù)雜的 UI 的組件。
容器和組件模式:該模式將表示(組件)與邏輯和狀態(tài)管理(容器)分開(kāi)。組件負(fù)責(zé)渲染 UI,而容器則處理業(yè)務(wù)邏輯和狀態(tài)管理。
功能切片設(shè)計(jì):它是一種用于組織和構(gòu)建 React 應(yīng)用程序的現(xiàn)代架構(gòu)方法。它旨在通過(guò)根據(jù)功能或模塊劃分應(yīng)用程序代碼庫(kù)來(lái)解決可擴(kuò)展性、可維護(hù)性和可重用性的挑戰(zhàn)。
44.什么是特征切片設(shè)計(jì)?
它是一種用于組織和構(gòu)建 React 應(yīng)用程序的現(xiàn)代架構(gòu)方法。它旨在通過(guò)根據(jù)功能或模塊劃分應(yīng)用程序代碼庫(kù)來(lái)解決可擴(kuò)展性、可維護(hù)性和可重用性的挑戰(zhàn)。
在功能切片設(shè)計(jì)中,應(yīng)用程序的每個(gè)功能或模塊都組織到一個(gè)單獨(dú)的目錄中,其中包含所有必要的組件、操作、reducers 和其他相關(guān)文件。這有助于保持代碼庫(kù)的模塊化和隔離性,使其更易于開(kāi)發(fā)、測(cè)試和維護(hù)。
功能切片設(shè)計(jì)促進(jìn)了關(guān)注點(diǎn)的清晰分離,并將功能封裝在各個(gè)功能中。這允許不同的團(tuán)隊(duì)或開(kāi)發(fā)人員獨(dú)立地處理不同的功能,而不必?fù)?dān)心沖突或依賴(lài)性。
還有就是可以去了解功能切片設(shè)計(jì)
文章來(lái)源:http://www.zghlxwxcb.cn/article/397.html
文章來(lái)源地址http://www.zghlxwxcb.cn/article/397.html
到此這篇關(guān)于44個(gè)常見(jiàn)的React前端面試問(wèn)題的文章就介紹到這了,更多相關(guān)內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!