【第904期】React 常見的面試題

2021-03-02 前端早讀課

前言

曾在微博上看到這麼一句話:現在在簡歷上不體現 React,Vue,Webpack 都不好意思了。 今日早讀文章來自 @johannlai 授權分享。

正文從這開始~

當你調用 setState 的時候,發生了什麼事?

當調用 setState 時,React會做的第一件事情是將傳遞給 setState 的對象合併到組件的當前狀態。這將啟動一個稱為一致化處理(reconciliation)的過程。一致化處理(reconciliation)的最終目標是以最有效的方式,根據這個新的狀態來更新UI。 為此,React將構建一個新的 React 元素樹(您可以將其視為 UI 的對象表示)。

一旦有了這個樹,為了弄清 UI 如何響應新的狀態而改變,React 會將這個新樹與上一個元素樹相比較(diff)。

(譯註:一致化處理(reconciliation)可理解為 React 內部將虛擬 DOM 同步更新到真實 DOM 的過程,包括新舊虛擬 DOM 的比較及計算最小 DOM 操作)

通過這樣, React 將會知道發生的確切變化,並且了解發生什麼變化以後,只需在絕對必要的情況下進行更新,即可最小化 UI 的佔用空間。

在 React 當中 Element 和 Component 有何區別?

簡單地說,一個 React element 描述了你想在屏幕上看到什麼。換個說法就是,一個 React element 是一些 UI 的對象表示。

一個 React Component 是一個函數或一個類,它可以接受輸入並返回一個 React element (通常是通過 JSX ,它被轉化成一個 createElement 調用)。

有關更多信息,請查看 React Elements vs React Components

什麼時候在功能組件( Functional Component )上使用類組件( Class Component)?

如果您的組件具有狀態( state )或生命周期方法,請使用 Class 組件。否則,使用功能組件。

什麼是 React 的 refs ,為什麼它們很重要?

refs 就像是一個逃生艙口,允許你直接訪問DOM元素或組件實例。為了使用它們,您可以向組件添加一個 ref 屬性,該屬性的值是一個回調函數,它將接收底層的 DOM 元素或組件的已掛接實例,作為其第一個參數。

class UnControlledForm extends Component {
 handleSubmit = () => {
   console.log("Input Value: ", this.input.value)
 }
 render () {
   return (
     <form onSubmit={this.handleSubmit}>
       <input
         type='text'
         ref={(input) => this.input = input} />
       <button type='submit'>Submit</button>
     </form>
   )
 }
}

以上注意到我們的輸入欄位有一個 ref 屬性,其值是一個函數。該函數接收放在實例上實際的 DOM 元素 input,以便在 handleSubmit 函數內部訪問它。經常被誤解的是,您需要使用類組件才能使用ref ,但 ref 也可以通過利用 JavaScript 中的閉包與 功能組件( functional components )一起使用。

function CustomForm ({handleSubmit}) {
 let inputElement
 return (
   <form onSubmit={() => handleSubmit(inputElement.value)}>
     <input
       type='text'
       ref={(input) => inputElement = input} />
     <button type='submit'>Submit</button>
   </form>
 )
}

React 中的 keys 是什麼,為什麼它們很重要?

keys 是幫助 React 跟蹤哪些項目已更改、添加或從列表中刪除的屬性。

return (
   <ul>
     {this.state.todoItems.map(({task, uid}) => {
       return <li key={uid}>{task}</li>
     })}
   </ul>
 )
}

每個keys 在兄弟元素之間是獨一無二的。我們已經談過幾次關於一致化處理(reconciliation)的過程,而且這個一致化處理過程(reconciliation)中的一部分正在執行一個新的元素樹與最前一個的差異。keys 使處理列表時更加高效,因為 React 可以使用子元素上的 keys 快速知道元素是新的還是在比較樹時才被移動的。

而且 keys 不僅使這個過程更有效率,而且沒有keys,React 不知道哪個本地狀態對應於移動中的哪個項目。所以當你 map 的時候,不要忽略了 keys 。

看下面的代碼: 如果您在 下創建了一個 React 元素,的組件定義將如何?

<Twitter username='tylermcginnis33'>
 {(user) => user === null
   ? <Loading />
   : <Badge info={user} />}
</Twitter>

import React, { Component, PropTypes } from 'react'
import fetchUser from 'twitter'



class Twitter extends Component {
 
}

如果你不熟悉渲染回調模式(render callback pattern),這將看起來有點奇怪。在這種模式中,一個組件接收一個函數作為它的 child。注意上面包含在 標籤內的內容。Twitter 組件的 child 是一個函數,而不是你曾經習以為常的一個組件。 這意味著在實現 Twitter 組件時,我們需要將 props.children 作為一個函數來處理。

以下是我的答案。

import React, { Component, PropTypes } from 'react'
import fetchUser from 'twitter'

class Twitter extends Component {
 state = {
   user: null,
 }
 static propTypes = {
   username: PropTypes.string.isRequired,
 }
 componentDidMount () {
   fetchUser(this.props.username)
     .then((user) => this.setState({user}))
 }
 render () {
   return this.props.children(this.state.user)
 }
}

值得注意的是,正如我上面提到的,我通過調用它並傳遞給 user 來把 props.children 處理為一個函數。

這種模式的好處是我們已經將父組件與子組件分離了。父組件管理狀態,父組件的調用者可以決定以何種方式將從父級接收的參數應用於他們的 UI。

為了演示這一點,我們假設在另一個文件中,我們要渲染一個 Profile 而不是一個 Badge,,因為我們使用渲染回調模式,所以我們可以輕鬆地交換 UI ,而不用改變我們對父(Twitter)組件的實現。

<Twitter username='tylermcginnis33'>
 {(user) => user === null
   ? <Loading />
   : <Profile info={user} />}
</Twitter>

受控組件( controlled component )與不受控制的組件( uncontrolled component )有什麼區別?

React 的很大一部分是這樣的想法,即組件負責控制和管理自己的狀態。

當我們將 native HTML 表單元素( input, select, textarea 等)投入到組合中時會發生什麼?我們是否應該使用 React 作為「單一的真理來源」,就像我們習慣使用React一樣? 或者我們是否允許表單數據存在 DOM 中,就像我們習慣使用HTML表單元素一樣? 這兩個問題是受控(controlled) VS 不受控制(uncontrolled)組件的核心。

受控組件是React控制的組件,也是表單數據的唯一真理來源。

如下所示,username 不存在於 DOM 中,而是以我們的組件狀態存在。每當我們想要更新 username 時,我們就像以前一樣調用setState。

class ControlledForm extends Component {
 state = {
   username: ''
 }
 updateUsername = (e) => {
   this.setState({
     username: e.target.value,
   })
 }
 handleSubmit = () => {}
 render () {
   return (
     <form onSubmit={this.handleSubmit}>
       <input
         type='text'
         value={this.state.username}
         onChange={this.updateUsername} />
       <button type='submit'>Submit</button>
     </form>
   )
 }
}

不受控制( uncontrolled component )的組件是您的表單數據由 DOM 處理,而不是您的 React 組件。

我們使用 refs 來完成這個。

class UnControlledForm extends Component {
 handleSubmit = () => {
   console.log("Input Value: ", this.input.value)
 }
 render () {
   return (
     <form onSubmit={this.handleSubmit}>
       <input
         type='text'
         ref={(input) => this.input = input} />
       <button type='submit'>Submit</button>
     </form>
   )
 }
}

雖然不受控制的組件通常更容易實現,因為您只需使用引用從DOM獲取值,但是通常建議您通過不受控制的組件來支持受控組件。

主要原因是受控組件支持即時欄位驗證,允許您有條件地禁用/啟用按鈕,強制輸入格式,並且更多的是 『the React way』。

在哪個生命周期事件中你會發出 AJAX 請求,為什麼?

AJAX 請求應該在 componentDidMount 生命周期事件中。 有幾個原因:

Fiber,是下一次實施React的和解算法,將有能力根據需要啟動和停止渲染,以獲得性能優勢。其中一個取捨之一是 componentWillMount,而在其他的生命周期事件中出發 AJAX 請求,將是具有 「非確定性的」。 這意味著 React 可以在需要時感覺到不同的時間開始調用 componentWillMount。這顯然是AJAX請求的不好方式。

您不能保證在組件掛載之前,AJAX請求已經 resolve。如果這樣做,那意味著你會嘗試在一個未掛載的組件上設置 SetState,這不僅不會起作用,反而會對你大喊大叫。 在 componentDidMount 中執行 AJAX 將保證至少有一個要更新的組件。

shouldComponentUpdate 應該做什麼,為什麼它很重要?

上面我們討論了 reconciliation ,什麼是 React 在 setState 被調用時所做的。在生命周期方法 shouldComponentUpdate 中,允許我們選擇退出某些組件(和他們的子組件)的 reconciliation 過程。

我們為什麼要這樣做?

如上所述,「一致化處理( reconciliation )的最終目標是以最有效的方式,根據新的狀態更新用戶界面」。如果我們知道我們的用戶界面(UI)的某一部分不會改變,那麼沒有理由讓 React 很麻煩地試圖去弄清楚它是否應該渲染。通過從 shouldComponentUpdate 返回 false,React 將假定當前組件及其所有子組件將保持與當前組件相同。

您如何告訴React 構建(build)生產模式,該做什麼?

通常,您將使用Webpack的 DefinePlugin 方法將 NODE_ENV 設置為 production。這將剝離像 propType 驗證和額外的警告。除此之外,還有一個好主意,可以減少你的代碼,因為React使用 Uglify 的 dead-code 來消除開發代碼和注釋,這將大大減少你的包的大小。

為什麼要使用 React.Children.map(props.children,()=>) 而不是 props.children.map(()=>)

因為不能保證props.children將是一個數組。

以此代碼為例,

<Parent>
 <h1>Welcome.</h1>
</Parent>

在父組件內部,如果我們嘗試使用 props.children.map 映射孩子,則會拋出錯誤,因為 props.children 是一個對象,而不是一個數組。

如果有多個子元素,React 只會使props.children成為一個數組。就像下面這樣:

<Parent>
 <h1>Welcome.</h1>
 <h2>props.children will now be an array</h2>
</Parent>

這就是為什麼你喜歡 React.Children.map,因為它的實現考慮到 props.children 可能是一個數組或一個對象。

描述事件在React中的處理方式

為了解決跨瀏覽器兼容性問題,您的 React 中的事件處理程序將傳遞SyntheticEvent 的實例,它是 React 的瀏覽器本機事件的跨瀏覽器包裝器。

這些 SyntheticEvent 與您習慣的原生事件具有相同的接口,除了它們在所有瀏覽器中都兼容。有趣的是,React 實際上並沒有將事件附加到子節點本身。React 將使用單個事件監聽器監聽頂層的所有事件。這對於性能是有好處的,這也意味著在更新DOM時,React 不需要擔心跟蹤事件監聽器。

createElement 和 cloneElement 有什麼區別?

createElement 是 JSX 被轉譯到的,是 React 用來創建 React Elements 的內容(一些 UI 的對象表示)。cloneElement用於克隆元素並傳遞新的 props。他們釘住了這兩個🙂的命名。

可以選擇性地傳遞給 setState 的第二個參數是什麼,它的目的是什麼?

一個回調函數,當setState結束並re-rendered該組件時將被調用。一些沒有說出來的東西是 setState 是異步的,這就是為什麼它需要一個第二個回調函數。通常最好使用另一個生命周期方法,而不是依賴這個回調函數,但是很高興知道它存在。

this.setState(
 { username: 'tylermcginnis33' },
 () => console.log('setState has finished and the component has re-rendered.')
)

這段代碼有什麼問題?

this.setState((prevState, props) => {
 return {
   streak: prevState.streak + props.count
 }
})

沒毛病。但是這種寫法很少被使用,並不是眾所周知的,就是你也可以傳遞一個函數給setState,它接收到先前的狀態和道具並返回一個新的狀態,正如我們在上面所做的那樣。它不僅沒有什麼問題,而且如果您根據以前的狀態(state)設置狀態,推薦使用這種寫法。

關於本文

譯者:@johannlai

譯文:http://johannlai.com/2017/04/09/React-Interview-Questions/

作者:@Tyler

原文:https://tylermcginnis.com/react-interview-questions/

相關焦點

  • React Status 中文周刊 #19 - React Hook發布兩周年回顧
    🔥 本周熱門React Hook 發布兩周年回顧 — 我們從 2018 年年末的第 112 期開始,引入了 Hook,此後 Hook 便勢不可擋。此文介紹了 Hook 的優缺點,以及 Hook 對 React 及其他框架帶來的影響(尤其是 Vue 和 Svelte)。
  • 2020 前端面試|第二波面試題總結
    前言哈,看樣子年後跳槽還是大家比較關心的一件事情了,繼第一波面試題匯總的反響和評論,觀看和點讚的朋友們很多,我繼續將後續面試的一些內容寫出來,有很多面試題答案我自己寫的比較含糊,但是在面試的過程中是描述的表較多的。畢竟寫文字要寫出來太多了。我也只是寫了一個大概,如果對答案不太滿意的同學可以自行查詢標準答案哈。
  • 【別笑】手撕吊打面試官系列面試題
    必備面試題js基礎1.用js列印一個乘法表這一題面試官考察的是你關於js的列印相關基礎api的熟悉程度,以及基本的數學常識,送分題console.log(`1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94*1=4 4*2=8 4*3=12 4*4=16
  • 【第1793期】理解 React 的下一步:Concurrent Mode 與 Suspense
    前言【第1773期】19 個來自 2019 React Conf 的總結 今日早讀文章由@林承澤分享。
  • 面試| 必須要會的50個React面試題
    如果你是一位有抱負的前端程式設計師並準備面試,那麼這篇文章很適合你。本文是你學習和面試 React 所需知識的***指南。JavaScript 工具緩慢而穩定地在市場中紮根,對 React 的需求呈指數級增長。選擇合適的技術來開發應用或網站變得越來越有挑戰性。
  • 2020Python常見面試題及答案-開課吧
    Python面試題【Python面試題】-iterable(可迭代對象)和iterator(迭代器)的區別?【Python面試題】怎樣聲明多個變量並賦值?addict 是第三方庫,需要先安裝 pip install addict from addict import Dictaddicted = Dict() addicted.a.b.c.d.e = "value"【Python面試題】如何提高python的運行效率?
  • 【第902期】React 的生命周期的使用場景
    最常見的用例: 啟動AJAX調用,以加載組件的數據。可以調用setState:是的。componentWillReceiveProps我們的組成部分做得很好,突然之間,一大堆新的 props 到達了,使到組件處於混亂狀態。
  • 為什麼我說你應該學React源碼?
    以下是我從阿里,字節,滴滴等大廠面經中摘取的React相關面試題:React 中的 setState 是同步還是異步React、Vue /Angular 的區別?(會根據你簡歷中寫的技術棧來)React 中各種組件復用的優劣勢(mixin、render props、hoc、hook)React新的生命周期,為什麼 getDrivedStatefromProps 是靜態的?
  • 面試題:React中setState是異步還是同步?
    在學習react的過程中幾乎所有學習材料都會反覆強調一點setState是異步的,來看一下react官網對於setState的說明。
  • 測試面試題集錦(一)| 軟體測試常見必考問題與流程篇(附答案)
    本系列文章總結歸納了一些軟體測試工程師常見的面試題,主要來源於個人面試遇到的、網絡搜集(完善)、工作日常討論等,分為以下十個部分,供大家參考。如有錯誤的地方,歡迎指正。有更多的面試題或面試中遇到的坑,也歡迎補充分享。希望大家都能找到滿意的工作,共勉之!
  • 第329天:React的refs的理解
    集成第三方DOM庫。使用React提供的這個ref屬性,表示為對組件真正實例的引用,其實就是ReactDOM.render()返回的組件實例,需要區分一下渲染組件與渲染原生DOM元素,渲染組件時返回的是組件實例,而渲染DOM元素時,返回是具體的DOM節點,React的ref有3種用法。
  • 數據分析師面試最常見的十道面試題分享!
    以下是容大教育小編日常整理的數據分析師面試時經常遇到的十道數據分析面試題,下面讓我們一起看看數據分析師面試最常見的十道面試題:1、海量日誌數據,提取出某日訪問百度次數最多的那個IP首先是這一天,並且是訪問百度的日誌中的IP取出來,逐個寫入到一個大文件中。
  • 【007期】JavaSE面試題(七):異常
    的提褲姐,今天這篇是面試系列的第七篇,主要總結了JavaSE中異常類相關面試題,在後續,會沿著第一篇開篇的知識線路一直總結下去,做到日更!寫出你最常見的 5 個 RuntimeException?(1)java.lang.NullPointerException 空指針異常;出現原因:調用了未經初始化的對象或者是不存在的對象。
  • 第285天:React生命周期
    此用法並不常見,但它可能出現在UI處理中,如需要以特殊方式處理滾動位置的聊天線程等。;meta charset="UTF-8" /> <title>React生命周期</title></head><body> <div id="root"></div></body><script src="https://unpkg.com/react
  • 【19】進大廠必須掌握的面試題-50個React面試
    點擊上方「全棧程式設計師社區」,星標公眾號這是最有可能由面試官提出的 常被問到的50個React面試問答。為了方便您訪問,我對React面試問題進行了歸類:React一般面試問題反應組件面試問題React Redux面試問題React Router面試問題一般React – React面試問題1.區分真實DOM和虛擬DOM。
  • 好程式設計師Python教程分享常見的Python面試題
    好程式設計師Python教程分享常見的Python面試題,程式設計師面試難免會需要進行筆試,筆試是考驗程式設計師基礎功底的重要環節,根據很多小夥伴的面試反饋,今天總結分享了一些常見的Python面試題,想要看Python面試是不是可以順利通過,這些常見的Python面試題你應該看看。
  • 常見結構化面試經典100題及答案查看
    常見結構化面試經典100題及答案查看由北京教師招聘考試網提供:更多關於結構化面試經典100題的內容請關注教師資格考試網/北京教師招聘考試網!或關注北京華圖微信公眾號(bjhuatu),北京教師考試培訓諮詢電話:400-010-1568。
  • Java 最常見的 200+ 面試題:面試必備
    聊回面試題這件事,這份面試清單原本是我們公司內部使用的,可到後來有很多朋友在微信上聯繫到我,讓我幫他們找一些面試方面的資料,而且這些關係也不太好拒絕,一呢,是因為這些找我,要面試題的人,不是我的好朋友的弟弟妹妹,就是我的弟弟妹妹們;二呢,我也不能馬馬虎虎的對付,受人之事忠人之命,我也不能辜負這份信任。
  • 2019年java常見面試題
    本人今年2月份來到上海來尋求工作,已經面試了10多家了,在這裡分享一下我的心得和常問到的面試題。,所以當面試官說回去等消息的時候,並不代表沒有機會,有時候需要討論篩選才能最終確定人選。走馬觀花式的學習;6、當遇到一些設計類的問題時,一般面試官考察的是你的思路,對問題的應變能力,對於事物觀察的點;技術面試題:
  • 前端面試題集合
    express和koa的對比,兩者中間件的原理,koa捕獲異常多種情況說一下你項目裡用到第三方登錄涉及的oAuth(JWT)協議的實現原理,以及你本地的實現原理,第三方登錄怎麼樣保證安全性說下快排完整性react和vue的區別,你開發如何選擇技術棧express裡面登錄的session服務怎麼樣實現分布式服務vue