写点什么

字节前端一面经典 react 面试题及答案

作者:beifeng1996
  • 2023-02-28
    浙江
  • 本文字数:5621 字

    阅读完需:约 18 分钟

setState 方法的第二个参数有什么用?使用它的目的是什么?

它是一个回调函数,当 setState 方法执行结束并重新渲染该组件时调用它。在工作中,更好的方式是使用 React 组件生命周期之——“存在期”的生命周期方法,而不是依赖这个回调函数。


export class App extends Component {  constructor(props) {    super(props);    this.state = {      username: "雨夜清荷",    };  }  render() {    return <div> {this.state.username}</div>;  }  componentDidMount() {    this.setstate(      {        username: "有课前端网",      },      () => console.log("re-rendered success. ")    );  }}
复制代码

React setState 笔试题,下面的代码输出什么

class Example extends React.Component {  constructor() {  super()  this.state = {    val: 0  }}componentDidMount() {  this.setState({ val: this.state.val + 1 })  console.log(this.state.val)  // 第 1 次 log  this.setState({ val: this.state.val + 1 })  console.log(this.state.val)  // 第 2 次 log  setTimeout(() => {    this.setState({ val: this.state.val + 1 })    console.log(this.state.val)    // 第 3 次 log    this.setState({ val: this.state.val + 1 })    console.log(this.state.val)    // 第 4 次 log    }, 0)  }  render() {    return null  }}
// 答:0, 0, 1, 2
复制代码

react 和 vue 的区别

相同点:


  1. 数据驱动页面,提供响应式的试图组件

  2. 都有 virtual DOM,组件化的开发,通过 props 参数进行父子之间组件传递数据,都实现了 webComponents 规范

  3. 数据流动单向,都支持服务器的渲染 SSR

  4. 都有支持 native 的方法,react 有 React native, vue 有 wexx


不同点:


  1. 数据绑定:Vue 实现了双向的数据绑定,react 数据流动是单向的

  2. 数据渲染:大规模的数据渲染,react 更快

  3. 使用场景:React 配合 Redux 架构适合大规模多人协作复杂项目,Vue 适合小快的项目

  4. 开发风格:react 推荐做法 jsx + inline style 把 html 和 css 都写在 js 了


vue 是采用 webpack +vue-loader 单文件组件格式,html, js, css 同一个文件

在哪个生命周期中你会发出 Ajax 请求?为什么?

Ajax 请求应该写在组件创建期的第五个阶段,即 componentDidMount 生命周期方法中。原因如下。在创建期的其他阶段,组件尚未渲染完成。而在存在期的 5 个阶段,又不能确保生命周期方法一定会执行(如通过 shouldComponentUpdate 方法优化更新等)。在销毀期,组件即将被销毁,请求数据变得无意义。因此在这些阶段发岀 Ajax 请求显然不是最好的选择。在组件尚未挂载之前,Ajax 请求将无法执行完毕,如果此时发出请求,将意味着在组件挂载之前更新状态(如执行 setState),这通常是不起作用的。在 componentDidMount 方法中,执行 Ajax 即可保证组件已经挂载,并且能够正常更新组件。

简述 flux 思想

Flux 的最大特点,就是数据的"单向流动"。


  • 用户访问 View

  • View发出用户的 Action

  • Dispatcher 收到Action,要求 Store 进行相应的更新

  • Store 更新后,发出一个"change"事件

  • View 收到"change"事件后,更新页面

React 中的 StrictMode(严格模式)是什么??

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


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

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

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


参考 前端进阶面试题详细解答

使用 React Hooks 好处是啥?

首先,Hooks 通常支持提取和重用跨多个组件通用的有状态逻辑,而无需承担高阶组件或渲染 props 的负担。Hooks 可以轻松地操作函数组件的状态,而不需要将它们转换为类组件。Hooks 在类中不起作用,通过使用它们,咱们可以完全避免使用生命周期方法,例如 componentDidMountcomponentDidUpdatecomponentWillUnmount。相反,使用像useEffect这样的内置钩子。

在使用 React Router 时,如何获取当前页面的路由或浏览器中地址栏中的地址?

在当前组件的 props 中,包含 location 属性对象,包含当前页面路由地址信息,在 match 中存储当前路由的参数等数据信息。可以直接通过 this .props 使用它们。

React 实现的移动应用中,如果出现卡顿,有哪些可以考虑的优化方案

  • 增加shouldComponentUpdate钩子对新旧props进行比较,如果值相同则阻止更新,避免不必要的渲染,或者使用PureReactComponent替代Component,其内部已经封装了shouldComponentUpdate的浅比较逻辑

  • 对于列表或其他结构相同的节点,为其中的每一项增加唯一key属性,以方便Reactdiff算法中对该节点的复用,减少节点的创建和删除操作

  • render函数中减少类似onClick={() => {doSomething()}}的写法,每次调用 render 函数时均会创建一个新的函数,即使内容没有发生任何变化,也会导致节点没必要的重渲染,建议将函数保存在组件的成员对象中,这样只会创建一次

  • 组件的props如果需要经过一系列运算后才能拿到最终结果,则可以考虑使用reselect库对结果进行缓存,如果 props 值未发生变化,则结果直接从缓存中拿,避免高昂的运算代价

  • webpack-bundle-analyzer分析当前页面的依赖包,是否存在不合理性,如果存在,找到优化点并进行优化

react 有什么优点

  • 提高应用性能

  • 可以方便的在客户端和服务端使用

  • 使用 jsx 模板进行数据渲染,可读性好

在 Reducer 文件里,对于返回的结果,要注意哪些问题?

在 Reducer 文件里,对于返回的结果,必须要使用 Object.assign ( )来复制一份新的 state,否则页面不会跟着数据刷新。


return Object.assign({}, state, {  type: action.type,  shouldNotPaint: true,});
复制代码

createElement 过程

React.createElement(): 根据指定的第一个参数创建一个 React 元素


React.createElement(  type,  [props],  [...children])
复制代码


  • 第一个参数是必填,传入的是似 HTML 标签名称,eg: ul, li

  • 第二个参数是选填,表示的是属性,eg: className

  • 第三个参数是选填, 子节点,eg: 要显示的文本内容


//写法一:
var child1 = React.createElement('li', null, 'one'); var child2 = React.createElement('li', null, 'two'); var content = React.createElement('ul', { className: 'teststyle' }, child1, child2); // 第三个参数可以分开也可以写成一个数组 ReactDOM.render( content, document.getElementById('example') );
//写法二:
var child1 = React.createElement('li', null, 'one'); var child2 = React.createElement('li', null, 'two'); var content = React.createElement('ul', { className: 'teststyle' }, [child1, child2]); ReactDOM.render( content, document.getElementById('example') );
复制代码

约束性组件( controlled component)与非约束性组件( uncontrolled  component)有什么区别?

在 React 中,组件负责控制和管理自己的状态。如果将 HTML 中的表单元素( input、 select、 textarea 等)添加到组件中,当用户与表单发生交互时,就涉及表单数据存储问题。根据表单数据的存储位置,将组件分成约東性组件和非约東性组件。约束性组件( controlled component)就是由 React 控制的组件,也就是说,表单元素的数据存储在组件内部的状态中,表单到底呈现什么由组件决定。如下所示, username 没有存储在 DOM 元素内,而是存储在组件的状态中。每次要更新 username 时,就要调用 setState 更新状态;每次要获取 username 的值,就要获取组件状态值。


class App extends Component {  //初始化状态  constructor(props) {    super(props);    this.state = {      username: "有课前端网",    };  }  //查看结果  showResult() {    //获取数据就是获取状态值    console.log(this.state.username);  }  changeUsername(e) {    //原生方法获取    var value = e.target.value;    //更新前,可以进行脏值检测    //更新状态    this.setState({      username: value,    });  }  //渲染组件  render() {    //返回虚拟DOM    return (      <div>        <p>          {/*输入框绑定va1ue*/}          <input type="text" onChange={this.changeUsername.bind(this)} value={this.state.username} />        </p>        <p>          <button onClick={this.showResult.bind(this)}>查看结果</button>        </p>      </div>    );  }}
复制代码


非约束性组件( uncontrolled component)就是指表单元素的数据交由元素自身存储并处理,而不是通过 React 组件。表单如何呈现由表单元素自身决定。如下所示,表单的值并没有存储在组件的状态中,而是存储在表单元素中,当要修改表单数据时,直接输入表单即可。有时也可以获取元素,再手动修改它的值。当要获取表单数据时,要首先获取表单元素,然后通过表单元素获取元素的值。注意:为了方便在组件中获取表单元素,通常为元素设置 ref 属性,在组件内部通过 refs 属性获取对应的 DOM 元素。


class App extends Component {  //查看结果  showResult() {    //获取值    console.log(this.refs.username.value);    //修改值,就是修改元素自身的值    this.refs.username.value = "专业前端学习平台";    //渲染组件    //返回虚拟DOM    return (      <div>        <p>          {/*非约束性组件中,表单元素通过 defaultvalue定义*/}          <input type="text" ref=" username" defaultvalue="有课前端网" />        </p>        <p>          <button onClick={this.showResult.bind(this)}>查看结果</button>        </p>      </div>    );  }}
复制代码


虽然非约東性组件通常更容易实现,可以通过 refs 直接获取 DOM 元素,并获取其值,但是 React 建议使用约束性组件。主要原因是,约東性组件支持即时字段验证,允许有条件地禁用/启用按钮,强制输入格式等。

根据下面定义的代码,可以找出存在的两个问题吗 ?

请看下面的代码:


图片描述


答案:1.在构造函数没有将 props 传递给 super,它应该包括以下行


constructor(props) {super(props);// ...}
复制代码


2.事件监听器(通过addEventListener()分配时)的作用域不正确,因为 ES6 不提供自动绑定。因此,开发人员可以在构造函数中重新分配clickHandler来包含正确的绑定:


constructor(props) {super(props);this.clickHandler = this.clickHandler.bind(this);// ...}
复制代码

讲讲什么是 JSX ?

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>    );  }}
复制代码

React 的生命周期方法有哪些?

  • componentWillMount:在渲染之前执行,用于根组件中的 App 级配置。

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

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

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

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

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

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

React 组件生命周期有哪些不同阶段?

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


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

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

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

  4. Unmounting:在这个阶段,组件已经不再被需要了,它从浏览器 DOM 中卸载下来。这个阶段包含 componentWillUnmount 生命周期方法。除以上四个常用生命周期外,还有一个错误处理的阶段:Error Handling:在这个阶段,不论在渲染的过程中,还是在生命周期方法中或是在任何子组件的构造函数中发生错误,该组件都会被调用。这个阶段包含了 componentDidCatch 生命周期方法。


clipboard.png

React 如何进行组件/逻辑复用?

抛开已经被官方弃用的 Mixin,组件抽象的技术目前有三种比较主流:


  • 高阶组件:

  • 属性代理

  • 反向继承

  • 渲染属性

  • react-hooks

Redux 中间件是怎么拿到 store 和 action? 然后怎么处理?

redux 中间件本质就是一个函数柯里化。redux applyMiddleware Api 源码中每个 middleware 接受 2 个参数, Store 的 getState 函数和 dispatch 函数,分别获得 store 和 action,最终返回一个函数。该函数会被传入 next 的下一个 middleware 的 dispatch 方法,并返回一个接收 action 的新函数,这个函数可以直接调用 next(action),或者在其他需要的时刻调用,甚至根本不去调用它。调用链中最后一个 middleware 会接受真实的 store 的 dispatch 方法作为 next 参数,并借此结束调用链。所以,middleware 的函数签名是({ getState,dispatch })=> next => action。

什么是 React Context?

Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。


用户头像

beifeng1996

关注

还未添加个人签名 2022-09-01 加入

还未添加个人简介

评论

发布
暂无评论
字节前端一面经典react面试题及答案_前端_beifeng1996_InfoQ写作社区