vlambda博客
学习文章列表

掌握了这些 React 面试题,不进阿里都难!

如果你是一位有抱负的前端程序员并准备面试,那么这篇文章很适合你。本文是你学习和面试  React  所需知识的完美指南。

JavaScript 工具缓慢而稳定地在市场中扎根,对 React 的需求呈指数级增长。选择合适的技术来开发应用或网站变得越来越有挑战性。其中 React 被认为是增长最快的 Javascript 框架。

本文阅读约需要30分钟,涉及的面试题有:

问题1:什么是虚拟DOM?

问题2:类组件和函数组件之间的区别是啥?

问题 3:React 中 refs 干嘛用的?

问题 4:redux中间件

问题 5:React生命周期函数

问题 6:在 React 中如何处理事件

问题 7:如何创建 refs

问题 8:什么是高阶组件?

问题 9:在构造函数调用 super 并将 props 作为参数传入的作用是啥?

问题 10:什么是控制组件?

问题 11:如何 React.createElement ?

问题 12:讲讲什么是 JSX ?

问题 13:为什么不直接更新 state 呢 ?

问题 14:React 组件生命周期有哪些不同阶段?

问题 15:React 的生命周期方法有哪些?

问题 16:这三个点(...)在 React 干嘛用的?

问题 17:使用 React Hooks 好处是啥?

问题 18:什么是 React Hooks?

问题 19:React 中的 useState() 是什么?

问题 20:React 中的StrictMode(严格模式)是什么?

问题 21:为什么类方法需要绑定到类实例?

问题 22:什么是 prop drilling,如何避免?

问题 23:描述 Flux 与 MVC?

问题 24:受控组件和非受控组件区别是啥?

问题 25:什么是Virtual DOM及其工作原理

问题 26:Redux Thunk 的作用是什么?

问题 27:当渲染一个列表时,何为key?设置key的目的是什么?

问题 28:如何在 ReactJS 的 Props上应用验证?

问题 29:如何有条件地向 React 组件添加属性?

问题 30:Hooks会取代 render props 和高阶组件吗?

问题 31:何为高阶组件(higher order component)?

问题 32:为什么建议传递给 setState 的参数是一个 callback 而不是一个对象?

问题 33:如何避免在React重新绑定实例?

问题 34:在 React 中使用构造函数和 getInitialState 有什么区别?

问题 35:何为纯函数(pure function)?

问题 36: 区分Real DOM和Virtual DO

问题 37:你了解 Virtual DOM 吗?解释一下它的工作原理

问题 38:与 ES5 相比,React 的 ES6 语法有何不同?

问题 39:如何更新状态以及如何让不更新 

问题 40:超越继承的组合

问题 41:如何在React中应用样式

问题 42:什么是错误边界

问题1:什么是虚拟DOM?

主题: React
难度: ⭐

虚拟 DOM (VDOM)是真实 DOM 在内存中的表示。UI 的表示形式保存在内存中,并与实际的 DOM 同步。这是一个发生在渲染函数被调用和元素在屏幕上显示之间的步骤,整个过程被称为调和

问题2:类组件和函数组件之间的区别是啥?

主题: React
难度: ⭐⭐
  • 类组件可以使用其他特性,如状态 state 和生命周期钩子。

  • 当组件只是接收 props 渲染到页面时,就是无状态组件,就属于函数组件,也被称为哑组件或展示组件。

函数组件和类组件当然是有区别的,而且函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。

区别 函数组件 类组件
是否有 this 没有
是否有生命周期 没有
是否有状态 state 没有

问题 3:React 中 refs 干嘛用的?

主题: React
难度: ⭐⭐

Refs 提供了一种访问在render方法中创建的 DOM 节点或者 React 元素的方法。在典型的数据流中,props 是父子组件交互的唯一方式,想要修改子组件,需要使用新的pros重新渲染它。凡事有例外,某些情况下咱们需要在典型数据流外,强制修改子代,这个时候可以使用 Refs

咱们可以在组件添加一个 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> ) }}

请注意,input 元素有一个ref属性,它的值是一个函数。该函数接收输入的实际 DOM 元素,然后将其放在实例上,这样就可以在 handleSubmit 函数内部访问它。

经常被误解的只有在类组件中才能使用 refs,但是refs也可以通过利用 JS 中的闭包与函数组件一起使用。

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

问题 4:redux中间件

主题: React
难度: ⭐⭐
中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action -> middlewares -> reducer 。这种机制可以让我们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。
常见的中间件:redux-logger:提供日志输出;redux-thunk:处理异步操作;redux-promise:处理异步操作;actionCreator的返回值是promise

问题 5:React生命周期函数

主题: React
难度: ⭐⭐
(一)初始化阶段:
getDefaultProps:获取实例的默认属性
getInitialState:获取每个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上
render:组件在这里生成虚拟的DOM节点
componentDidMount:组件真正在被装载之后
(二)运行中状态:
componentWillReceiveProps:组件将要接收到属性的时候调用
shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回false,接收数据后不更新,阻止render调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件重新描绘
componentDidUpdate:组件已经更新
(三)销毁阶段:
componentWillUnmount:组件即将销毁

问题 6:在 React 中如何处理事件

主题: React
难度: ⭐⭐

为了解决跨浏览器的兼容性问题,SyntheticEvent 实例将被传递给你的事件处理函数,SyntheticEvent是 React 跨浏览器的浏览器原生事件包装器,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()

比较有趣的是,React 实际上并不将事件附加到子节点本身。React 使用单个事件侦听器侦听顶层的所有事件。这对性能有好处,也意味着 React 在更新 DOM 时不需要跟踪事件监听器。

问题 7:如何创建 refs

主题: React
难度: ⭐⭐

Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; }}

或者这样用:

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

问题 8:什么是高阶组件?

主题: React
难度: ⭐⭐

高阶组件(HOC)是接受一个组件并返回一个新组件的函数。基本上,这是一个模式,是从 React 的组合特性中衍生出来的,称其为纯组件,因为它们可以接受任何动态提供的子组件,但不会修改或复制输入组件中的任何行为。

const EnhancedComponent = higherOrderComponent(WrappedComponent);

HOC 可以用于以下许多用例

  • 代码重用、逻辑和引导抽象

  • 渲染劫持

  • state 抽象和操作

  • props 处理

问题 9:在构造函数调用 super 并将 props 作为参数传入的作用是啥?

主题: React
难度: ⭐⭐

在调用 super() 方法之前,子类构造函数无法使用this引用,ES6 子类也是如此。将 props 参数传递给 super() 调用的主要原因是在子构造函数中能够通过this.props来获取传入的 props

传递 props

class MyComponent extends React.Component { constructor(props) { super(props); console.log(this.props); // { name: 'sudheer',age: 30 } }}

没传递 props

class MyComponent extends React.Component { constructor(props) { super(); console.log(this.props); // undefined // 但是 Props 参数仍然可用 console.log(props); // Prints { name: 'sudheer',age: 30 } }
render() { // 构造函数外部不受影响 console.log(this.props) // { name: 'sudheer',age: 30 } }}

上面示例揭示了一点。props 的行为只有在构造函数中是不同的,在构造函数之外也是一样的。

问题 10:什么是控制组件?

主题: React
难度: ⭐⭐⭐

在 HTML 中,表单元素如 <input><textarea><select>通常维护自己的状态,并根据用户输入进行更新。当用户提交表单时,来自上述元素的值将随表单一起发送。

而 React 的工作方式则不同。包含表单的组件将跟踪其状态中的输入值,并在每次回调函数(例如onChange)触发时重新渲染组件,因为状态被更新。以这种方式由 React 控制其值的输入表单元素称为受控组件

问题 11:如何 React.createElement ?

主题: React
难度: ⭐⭐⭐

问题:

const element = ( <h1 className="greeting"> Hello, world! </h1>)

上述代码如何使用 React.createElement 来实现:

const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!');

掌握了这些 React 面试题,不进阿里都难!

问题 12:讲讲什么是 JSX ?

主题: React
难度: ⭐⭐⭐

当 Facebook 第一次发布 React 时,他们还引入了一种新的 JS 方言 JSX,将原始 HTML 模板嵌入到 JS 代码中。JSX 代码本身不能被浏览器读取,必须使用Babelwebpack等工具将其转换为传统的JS。很多开发人员就能无意识使用 JSX,因为它已经与 React 结合在一直了。

class MyComponent extends React.Component { render() {let props = this.props; return (<div className="my-component"><a href={props.url}>{props.name}</a></div> ); }}

问题 13:为什么不直接更新 state 呢 ?

主题: React
难度: ⭐⭐⭐

如果试图直接更新 state ,则不会重新渲染组件。

 // 错误 This.state.message = 'Hello world';

需要使用setState()方法来更新 state。它调度对组件state对象的更新。当state改变时,组件通过重新渲染来响应:

// 正确做法This.setState({message: ‘Hello World’});

问题 14:React 组件生命周期有哪些不同阶段?

主题: React
难度: ⭐⭐⭐

在组件生命周期中有四个不同的阶段:

  1. Initialization:在这个阶段,组件准备设置初始化状态和默认属性。

  2. Mounting:react 组件已经准备好挂载到浏览器 DOM 中。这个阶段包括componentWillMountcomponentDidMount生命周期方法。

  3. Updating:在这个阶段,组件以两种方式更新,发送新的 props 和 state 状态。此阶段包括shouldComponentUpdatecomponentWillUpdatecomponentDidUpdate生命周期方法。

  4. Unmounting:在这个阶段,组件已经不再被需要了,它从浏览器 DOM 中卸载下来。这个阶段包含 componentWillUnmount 生命周期方法。

除以上四个常用生命周期外,还有一个错误处理的阶段:

Error Handling:在这个阶段,不论在渲染的过程中,还是在生命周期方法中或是在任何子组件的构造函数中发生错误,该组件都会被调用。这个阶段包含了 componentDidCatch 生命周期方法。

掌握了这些 React 面试题,不进阿里都难!

问题 15:React 的生命周期方法有哪些?

主题: React
难度: ⭐⭐⭐
  • componentWillMount:在渲染之前执行,用于根组件中的 App 级配置。

  • componentDidMount:在第一次渲染之后执行,可以在这里做AJAX请求,DOM 的操作或状态更新以及设置事件监听器。

  • componentWillReceiveProps:在初始化render的时候不会执行,它会在组件接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染

  • shouldComponentUpdate:确定是否更新组件。默认情况下,它返回true。如果确定在 state 或 props 更新后组件不需要在重新渲染,则可以返回false,这是一个提高性能的方法。

  • componentWillUpdate:在shouldComponentUpdate返回 true 确定要更新组件之前件之前执行。

  • componentDidUpdate:它主要用于更新DOM以响应propsstate更改。

  • componentWillUnmount:它用于取消任何的网络请求,或删除与组件关联的所有事件监听器。

掌握了这些 React 面试题,不进阿里都难!

问题 16:这三个点(...)在 React 干嘛用的?

主题: React
难度: ⭐⭐⭐

... 在React(使用JSX)代码中做什么?它叫什么?

<Modal {...this.props} title='Modal heading' animation={false}/>

这个叫扩展操作符号或者展开操作符,例如,如果this.props包含a:1b:2,则

<Modal {...this.props} title='Modal heading' animation={false}>

等价于下面内容:

<Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>

扩展符号不仅适用于该用例,而且对于创建具有现有对象的大多数(或全部)属性的新对象非常方便,在更新state 咱们就经常这么做:

this.setState(prevState => { return {foo: {...prevState.foo, a: "updated"}};});

问题 17:使用 React Hooks 好处是啥?

主题: React
难度: ⭐⭐⭐

首先,Hooks 通常支持提取和重用跨多个组件通用的有状态逻辑,而无需承担高阶组件或渲染 props 的负担。Hooks 可以轻松地操作函数组件的状态,而不需要将它们转换为类组件。

Hooks 在类中不起作用,通过使用它们,咱们可以完全避免使用生命周期方法,例如 componentDidMountcomponentDidUpdatecomponentWillUnmount。相反,使用像useEffect这样的内置钩子。

问题 18:什么是 React Hooks?

主题: React
难度: ⭐⭐⭐

Hooks是 React 16.8 中的新添加内容。它们允许在不编写类的情况下使用state和其他 React 特性。使用 Hooks,可以从组件中提取有状态逻辑,这样就可以独立地测试和重用它。Hooks 允许咱们在不改变组件层次结构的情况下重用有状态逻辑,这样在许多组件之间或与社区共享 Hooks 变得很容易。

掌握了这些 React 面试题,不进阿里都难!

问题 19:React 中的 useState() 是什么?

主题: React
难度: ⭐⭐⭐

下面说明useState(0)的用途:

...const [count, setCounter] = useState(0);const [moreStuff, setMoreStuff] = useState(...);...
const setCount = () => { setCounter(count + 1); setMoreStuff(...); ...};

useState 是一个内置的 React Hook。useState(0) 返回一个元组,其中第一个参数count是计数器的当前状态,setCounter 提供更新计数器状态的方法。

咱们可以在任何地方使用setCounter方法更新计数状态-在这种情况下,咱们在setCount函数内部使用它可以做更多的事情,使用 Hooks,能够使咱们的代码保持更多功能,还可以避免过多使用基于类的组件。

问题 20:React 中的StrictMode(严格模式)是什么?

主题: React
难度: ⭐⭐⭐

React 的StrictMode是一种辅助组件,可以帮助咱们编写更好的 react 组件,可以使用<StrictMode />包装一组组件,并且可以帮咱们以下检查:

  • 验证内部组件是否遵循某些推荐做法,如果没有,会在控制台给出警告。

  • 验证是否使用的已经废弃的方法,如果有,会在控制台给出警告。

  • 通过识别潜在的风险预防一些副作用。

问题 21:为什么类方法需要绑定到类实例?

主题: React
难度: ⭐⭐⭐

在 JS 中,this 值会根据当前上下文变化。在 React 类组件方法中,开发人员通常希望 this 引用组件的当前实例,因此有必要将这些方法绑定到实例。通常这是在构造函数中完成的:

class SubmitButton extends React.Component { constructor(props) { super(props); this.state = { isFormSubmitted: false }; this.handleSubmit = this.handleSubmit.bind(this); }
handleSubmit() { this.setState({ isFormSubmitted: true }); }
render() { return ( <button onClick={this.handleSubmit}>Submit</button> ) }}

问题 22:什么是 prop drilling,如何避免?

主题: React
难度: ⭐⭐⭐

在构建 React 应用程序时,在多层嵌套组件来使用另一个嵌套组件提供的数据。最简单的方法是将一个 prop 从每个组件一层层的传递下去,从源组件传递到深层嵌套组件,这叫做prop drilling

prop drilling的主要缺点是原本不需要数据的组件变得不必要地复杂,并且难以维护。

为了避免prop drilling,一种常用的方法是使用React Context。通过定义提供数据的Provider组件,并允许嵌套的组件通过Consumer组件或useContext Hook 使用上下文数据。

问题 23:描述 Flux 与 MVC?

主题: React
难度: ⭐⭐⭐

传统的 MVC 模式在分离数据(Model)、UI(View和逻辑(Controller)方面工作得很好,但是 MVC 架构经常遇到两个主要问题:

数据流不够清晰:跨视图发生的级联更新常常会导致混乱的事件网络,难于调试。

缺乏数据完整性:模型数据可以在任何地方发生突变,从而在整个UI中产生不可预测的结果。

使用 Flux 模式的复杂用户界面不再遭受级联更新,任何给定的React 组件都能够根据 store 提供的数据重建其状态。Flux 模式还通过限制对共享数据的直接访问来加强数据完整性。

问题 24:受控组件和非受控组件区别是啥?

主题: React
难度: ⭐⭐⭐
  • 受控组件是 React 控制中的组件,并且是表单数据真实的唯一来源。

  • 非受控组件是由 DOM 处理表单数据的地方,而不是在 React 组件中。

尽管非受控组件通常更易于实现,因为只需使用refs即可从 DOM 中获取值,但通常建议优先选择受控制的组件,而不是非受控制的组件。

这样做的主要原因是受控组件支持即时字段验证,允许有条件地禁用/启用按钮,强制输入格式。

问题 25:什么是Virtual DOM及其工作原理

主题: React
难度: ⭐⭐
React 使用 Virtual DOM 来更新真正的 DOM,从而提高效率和速度。我们来详细讨论这些。
什么是Virtual DOM?浏览器遵循HTML指令来构造文档对象模型(DOM)。当浏览器加载HTML并呈现用户界面时,HTML文档中的所有元素都变成DOM元素。
DOM是从根元素开始的元素层次结构。例如,看看下面的HTML。
<div><div><h1>This is heading</h1><p>this is paragraph</p><div><p>This is just a paragraon</p></div></div><div><h1>This is heading</h1><p>this is paragraph</p><div><p>This is just a paragraon</p></div></div><div><h1>This is heading</h1><p>this is paragraph</p><div><p>This is just a paragraon</p></div></div></div>
当在浏览器中加载这个HTML时,所有这些HTML元素都被转换成DOM元素。当涉及到SPA应用程序时,首次加载index.html,并在index.html本身中加载更新后的数据或另一个html。当用户浏览站点时,我们使用新内容更新相同的index.html。每当DOM发生更改时,浏览器都需要重新计算CSS、进行布局并重新绘制web页面。
React 使用 Virtual DOM 有效地重建 DOM。对于我们来说,这使得DOM操作的一项非常复杂和耗时的任务变得更加容易。React从开发人员那里抽象出所有这些,以便在Virtual DOM的帮助下构建高效的UI。
虚拟DOM是如何工作的?虚拟DOM只不过是真实 DOM 的 javascript对象表示。与更新真实 DOM 相比,更新 javascript 对象更容易,更快捷。考虑到这一点,让我们看看它是如何工作的。
React将整个DOM副本保存为虚拟DOM
掌握了这些 React 面试题,不进阿里都难!
每当有更新时,它都会维护两个虚拟DOM,以比较之前的状态和当前状态,并确定哪些对象已被更改。例如,段落文本更改为更改。
掌握了这些 React 面试题,不进阿里都难!
现在,它通过比较两个虚拟DOM 差异,并将这些变化更新到实际DOM
掌握了这些 React 面试题,不进阿里都难!
一旦真正的DOM更新,它也会更新UI

掌握了这些 React 面试题,不进阿里都难!

问题 26:Redux Thunk 的作用是什么?
主题: React
难度: ⭐⭐⭐⭐

Redux thunk 是一个允许你编写返回一个函数而不是一个 action 的 actions creators 的中间件。如果满足某个条件,thunk 则可以用来延迟 action 的派发(dispatch),这可以处理异步 action 的派发(dispatch)。

问题 27:当渲染一个列表时,何为key?设置key的目的是什么?

主题: React
难度: ⭐⭐⭐⭐

Keys 会有助于 React 识别哪些 items 改变了,被添加了或者被移除了。Keys 应该被赋予数组内的元素以赋予(DOM)元素一个稳定的标识,选择一个 key 的最佳方法是使用一个字符串,该字符串能惟一地标识一个列表项。很多时候你会使用数据中的 IDs 作为 keys,当你没有稳定的 IDs 用于被渲染的 items 时,可以使用项目索引作为渲染项的 key,但这种方式并不推荐,如果 items 可以重新排序,就会导致 re-render 变慢。

问题 28:如何在 ReactJS 的 Props上应用验证?

主题: React
难度: ⭐⭐⭐⭐

当应用程序在开发模式下运行时,React 将自动检查咱们在组件上设置的所有 props,以确保它们具有正确的数据类型。对于不正确的类型,开发模式下会在控制台中生成警告消息,而在生产模式中由于性能影响而禁用它。强制的 props 用 isRequired定义的。

下面是一组预定义的 prop 类型:

  • React.PropTypes.string

  • React.PropTypes.number

  • React.PropTypes.func

  • React.PropTypes.node

  • React.PropTypes.bool

例如,咱们为用户组件定义了如下的propTypes

import PropTypes from 'prop-types';
class User extends React.Component { render() { return ( <h1>Welcome, {this.props.name}</h1> <h2>Age, {this.props.age} ); }}
User.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number.isRequired};

问题 29:如何有条件地向 React 组件添加属性?

主题: React
难度: ⭐⭐⭐⭐

对于某些属性,React 非常聪明,如果传递给它的值是虚值,可以省略该属性。例如:

 
var InputComponent = React.createClass({ render: function() { var required = true; var disabled = false;
return ( <input type="text" disabled={disabled} required={required} /> ); }});

渲染结果:

<input type="text" required>

另一种可能的方法是:

var condition = true;
var component = ( <div value="foo" { ...( condition && { disabled: true } ) } />);

问题 30:Hooks会取代 render props 和高阶组件吗?

主题: React
难度: ⭐⭐⭐⭐

通常,render props和高阶组件仅渲染一个子组件。React团队认为,Hooks 是服务此用例的更简单方法。

这两种模式仍然有一席之地(例如,一个虚拟的 scroller 组件可能有一个 renderItem prop,或者一个可视化的容器组件可能有它自己的 DOM 结构)。但在大多数情况下,Hooks 就足够了,可以帮助减少树中的嵌套。

掌握了这些 React 面试题,不进阿里都难!

问题 31:何为高阶组件(higher order component)?

主题: React
难度: ⭐⭐⭐⭐

高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。

问题 32:为什么建议传递给 setState 的参数是一个 callback 而不是一个对象?

主题: React
难度: ⭐⭐⭐⭐⭐

因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state。

问题 33:如何避免在React重新绑定实例?

主题: React
难度: ⭐⭐⭐⭐⭐

有几种常用方法可以避免在 React 中绑定方法:

1.将事件处理程序定义为内联箭头函数

class SubmitButton extends React.Component { constructor(props) { super(props); this.state = { isFormSubmitted: false }; }
render() { return ( <button onClick={() => { this.setState({ isFormSubmitted: true }); }}>Submit</button> ) }}

2.使用箭头函数来定义方法:

class SubmitButton extends React.Component { state = { isFormSubmitted: false }
handleSubmit = () => { this.setState({ isFormSubmitted: true }); }
render() { return ( <button onClick={this.handleSubmit}>Submit</button> ) }}

3.使用带有 Hooks 的函数组件

const SubmitButton = () => { const [isFormSubmitted, setIsFormSubmitted] = useState(false);
return ( <button onClick={() => { setIsFormSubmitted(true); }}>Submit</button> )};

问题 34:在 React 中使用构造函数和 getInitialState 有什么区别?

主题: React
难度: ⭐⭐⭐⭐

构造函数和getInitialState之间的区别就是ES6ES5本身的区别。在使用ES6类时,应该在构造函数中初始化state,并在使用React.createClass时定义getInitialState方法。

class MyComponent extends React.Component { constructor(props) { super(props); this.state = { /* initial state */ }; }}

等价于:

var MyComponent = React.createClass({ getInitialState() {return { /* initial state */ }; },});

问题 35:何为纯函数(pure function)?

主题: React
难度: ⭐⭐

一个纯函数是一个不依赖于且不改变其作用域之外的变量状态的函数,这也意味着一个纯函数对于同样的参数总是返回同样的结果。

问题 36: 区分Real DOM和Virtual DO

主题: React
难度: ⭐⭐

掌握了这些 React 面试题,不进阿里都难!

问题 37:你了解 Virtual DOM 吗?解释一下它的工作原理

主题: React
难度: ⭐⭐

Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。

Virtual DOM 工作过程有三个简单的步骤。

1. 每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲染。

掌握了这些 React 面试题,不进阿里都难!

2. 然后计算之前 DOM 表示与新表示的之间的差异。

3. 完成计算后,将只用实际更改的内容更新 real DOM。

问题 38:与 ES5 相比,React 的 ES6 语法有何不同?

主题: React
难度: ⭐⭐

1.require 与 import

// ES5var React = require('react');// ES6import React from 'react';

2.export 与 exports

// ES5module.exports = Component;// ES6export default Component;

3.component 和 function

// ES5 var MyComponent = React.createClass({     renderfunction({         return             <h3>Hello Edureka!</h3>;     } });  // ES6class MyComponent extends React.Component {    render() {        return            <h3>Hello Edureka!</h3>;   }}

4.props

// ES5var App = React.createClass({ propTypes: { name: React.PropTypes.string }, render: function() { return <h3>Hello, {this.props.name}!</h3>; } });// ES6class App extends React.Component { render() { return <h3>Hello, {this.props.name}!</h3>; }}

5.state

// ES5 var App = React.createClass({getInitialState: function() {return { name: 'world' }; },render: function() {return<h3>Hello, {this.state.name}!</h3>; }});// ES6class App extends React.Component {constructor() {super();this.state = { name: 'world' }; } render() { return  <h3>Hello, {this.state.name}!</h3>; }}

问题 39:如何更新状态以及如何让不更新 

主题: React
难度: ⭐⭐
该直接修改状态。 可以在构造函数中定义状态值。 直接使用状态不会触发重新渲染。 React 使用this.setState()时合并状态。
// 错误方式this.state.name = "some name"// 正确方式this.setState({name:"some name"})
使用this.setState()的第二种形式总是更安全的,因为更新的props和状态是异步的。这里,我们根据这些 props 更新状态。
  
    
    
  
// 错误方式 this.setState({ timesVisited: this.state.timesVisited + this.props.count }) // 正确方式 this.setState((state, props) => { timesVisited: state.timesVisited + props.count });


问题 40:超越继承的组合

主题: React
难度: ⭐⭐
在React中,我们总是使用组合而不是继承。 我们已经在函数式编程部分讨论了什么是组合。 这是一种结合简单的可重用函数来生成高阶组件的技术。 下面是一个组合的例子,我们在 dashboard 组件中使用两个小组件todoForm和todoList。
import React from 'react';import '../App.css';import { ToDoForm } from './todoform';import { ToDolist } from './todolist';export class Dashboard extends React.Component { render() {return (<div className="dashboard"><ToDoForm /><ToDolist /></div> ); }}


问题 41:如何在React中应用样式

主题: React
难度: ⭐⭐
将样式应用于React组件有三种方法。
1.外部样式表
在此方法中,你可以将外部样式表导入到组件使用类中。但是你应该使用className而不是class来为React元素应用样式, 这里有一个例子。
import React from 'react';import './App.css';import { Header } from './header/header';import { Footer } from './footer/footer';import { Dashboard } from './dashboard/dashboard';import { UserDisplay } from './userdisplay';
function App() {return (<div className="App"><Header /><Dashboard /><UserDisplay /><Footer /></div> );}
export default App;
2.内联样式
在这个方法中,我们可以直接将 props 传递给HTML元素,属性为style。这里有一个例子。这里需要注意的重要一点是,我们将javascript对象传递给style,这就是为什么我们使用 backgroundColor 而不是CSS方法backbackground -color。
import React from 'react';
export const Header = () => {
const heading = 'TODO App'
return(<div style={{backgroundColor:'orange'}}><h1>{heading}</h1></div> )}
3.定义样式对象并使用它
因为我们将javascript对象传递给style属性,所以我们可以在组件中定义一个style对象并使用它。下面是一个示例,你也可以将此对象作为 props 传递到组件树中。
import React from 'react';const footerStyle = {width: '100%',backgroundColor: 'green',padding: '50px',font: '30px',color: 'white',fontWeight: 'bold'}export const Footer = () => {return(<div style={footerStyle}> All Rights Reserved 2019</div> )}

Action: Action 只是一个简单的json对象,type 和有payload作为键。type 是必须要有的,payload是可选的。下面是一个 action 的例子。
  
    
    
  
// action
{ type:"SEND_EMAIL", payload: data };
Action Creators:这些是创建Actions的函数,因此我们在派发action时不必在组件中手动编写每个 action。以下是 action creator 的示例。
  
    
    
  
// action creator
export function sendEamil(data) { return { type:"SEND_EMAIL", payload: data}; }
Reducers:Reducers 是纯函数,它将 action和当前 state 作为参数,计算必要的逻辑并返回一个新r的state。这些 Reducers 没有任何副作用。它不会改变 state 而是总是返回 state 。
  
    
    
  
export default function emailReducer(state = [], action){
switch(action.type) { case "SEND_EMAIL": return Object.assign({}, state, { email: action.payload }); default: return state; } }

组件如何与 redux 进行连接

mapStateToProps:此函数将state映射到 props 上,因此只要state发生变化,新 state 会重新映射到 props。这是订阅store的方式。
mapDispatchToProps:此函数用于将 action creators 绑定到你的props 。以便我们可以在第12行中使用This . props.actions.sendemail()来派发一个动作。
connect和bindActionCreators来自 redux。前者用于连接 store ,如第22行,后者用于将 action creators 绑定到你的 props ,如第20行。
  
    
    
  
// import connect import { connect } from 'react-redux' import { bindActionCreators } from 'redux'
// import action creators import * as userActions from '../../../actions/userActions';
export class User extends React.Component {
handleSubmit() { // dispatch an action this.props.actions.sendEmail(this.state.email); }
}
// you are mapping you state props const mapStateToProps = (state, ownProps) => ({user: state.user}) // you are binding your action creators to your props const mapDispatchToProps = (dispatch) => ({actions: bindActionCreators(userActions, dispatch)})
export default connect(mapStateToProps, mapDispatchToProps)(User);


问题 42:什么是错误边界

主题: React
难度: ⭐⭐
在 React 中,我们通常有一个组件树。 如果任何一个组件发生错误,它将破坏整个组件树。 没有办法捕捉这些错误,我们可以用错误边界优雅地处理这些错误。
错误边界有两个作用
如果发生错误,显示回退UI记录错误
下面是ErrorBoundary类的一个例子。如果类实现了 getDerivedStateFromError或componentDidCatch 这两个生命周期方法的任何一下,,那么这个类就会成为ErrorBoundary。前者返回{hasError: true}来呈现回退UI,后者用于记录错误。
  
    
    
  
import React from 'react'
export class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; }
static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; }
componentDidCatch(error, info) { // You can also log the error to an error reporting service console.log('Error::::', error); }
render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>OOPS!. WE ARE LOOKING INTO IT.</h1>; }
return this.props.children; } }
以下是我们如何在其中一个组件中使用ErrorBoundary。使用ErrorBoundary类包裹 ToDoForm和ToDoList。如果这些组件中发生任何错误,我们会记录错误并显示回退UI。
import React from 'react';import '../App.css';import { ToDoForm } from './todoform';import { ToDolist } from './todolist';import { ErrorBoundary } from '../errorboundary';export class Dashboard extends React.Component { render() {return (<div className="dashboard"><ErrorBoundary><ToDoForm /><ToDolist /></ErrorBoundary></div> ); }}