写点什么

2022react 高频面试题有哪些

作者:beifeng1996
  • 2022 年 9 月 25 日
    浙江
  • 本文字数:10529 字

    阅读完需:约 35 分钟

(在构造函数中)调用 super(props) 的目的是什么

super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 propssuper() 的原因则是便于(在子类中)能在 constructor 访问 this.props

你对【单一数据源】有什么理解

redux 使用 store 将程序的整个状态存储在同一个地方,因此所有组件的状态都存储在 Store 中,并且它们从 Store 本身接收更新。单一状态树可以更容易地跟踪随时间的变化,并调试或检查程序


前端react面试题详细解答

什么是控制组件?

在 HTML 中,表单元素如 <input><textarea><select>通常维护自己的状态,并根据用户输入进行更新。当用户提交表单时,来自上述元素的值将随表单一起发送。而 React 的工作方式则不同。包含表单的组件将跟踪其状态中的输入值,并在每次回调函数(例如onChange)触发时重新渲染组件,因为状态被更新。以这种方式由 React 控制其值的输入表单元素称为受控组件

hooks 为什么不能放在条件判断里

以 setState 为例,在 react 内部,每个组件(Fiber)的 hooks 都是以链表的形式存在 memoizeState 属性中



update 阶段,每次调用 setState,链表就会执行 next 向后移动一步。如果将 setState 写在条件判断中,假设条件判断不成立,没有执行里面的 setState 方法,会导致接下来所有的 setState 的取值出现偏移,从而导致异常发生。

Redux 内部原理 内部怎么实现 dispstch 一个函数的

redux-thunk中间件作为例子,下面就是thunkMiddleware函数的代码


// 部分转为ES5代码,运行middleware函数会返回一个新的函数,如下:return ({ dispatch, getState }) => {    // next实际就是传入的dispatch    return function (next) {        return function (action) {            // redux-thunk核心            if (typeof action === 'function') {                 return action(dispatch, getState, extraArgument);            }            return next(action);        };    };}
复制代码


redux-thunk库内部源码非常的简单,允许action是一个函数,同时支持参数传递,否则调用方法不变


  • redux创建Store:通过combineReducers函数合并reducer函数,返回一个新的函数combination(这个函数负责循环遍历运行reducer函数,返回全部state)。将这个新函数作为参数传入createStore函数,函数内部通过 dispatch,初始化运行传入的combination,state 生成,返回 store 对象

  • redux中间件:applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回经过中间件处理的新的dispatch函数

  • redux使用:实际就是再次调用循环遍历调用reducer函数,更新state

使用 React Hooks 好处是啥?

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

组件之间传值

  • 父组件给子组件传值

  • 在父组件中用标签属性的=形式传值

  • 在子组件中使用 props 来获取值

  • 子组件给父组件传值

  • 在组件中传递一个函数

  • 在子组件中用 props 来获取传递的函数,然后执行该函数

  • 在执行函数的时候把需要传递的值当成函数的实参进行传递

  • 兄弟组件之间传值

  • 利用父组件

  • 先把数据通过 【子组件】===》【父组件】

  • 然后在数据通过 【父组件】===〉【子组件】

  • 消息订阅

  • 使用 PubSubJs 插件

React diff 算法的原理是什么?

实际上,diff 算法探讨的就是虚拟 DOM 树发生变化后,生成 DOM 树更新补丁的方式。它通过对比新旧两株虚拟 DOM 树的变更差异,将更新补丁作用于真实 DOM,以最小成本完成视图更新。 具体的流程如下:


  • 真实的 DOM 首先会映射为虚拟 DOM;

  • 当虚拟 DOM 发生变化后,就会根据差距计算生成 patch,这个 patch 是一个结构化的数据,内容包含了增加、更新、移除等;

  • 根据 patch 去更新真实的 DOM,反馈到用户的界面上。

  • 一个简单的例子:


import React from 'react'export default class ExampleComponent extends React.Component {  render() {    if(this.props.isVisible) {       return <div className="visible">visbile</div>;    }     return <div className="hidden">hidden</div>;  }}
复制代码


这里,首先假定 ExampleComponent 可见,然后再改变它的状态,让它不可见 。映射为真实的 DOM 操作是这样的,React 会创建一个 div 节点。


<div class="visible">visbile</div>
复制代码


当把 visbile 的值变为 false 时,就会替换 class 属性为 hidden,并重写内部的 innerText 为 hidden。这样一个生成补丁、更新差异的过程统称为 diff 算法。


diff 算法可以总结为三个策略,分别从树、组件及元素三个层面进行复杂度的优化:


策略一:忽略节点跨层级操作场景,提升比对效率。(基于树进行对比)


这一策略需要进行树比对,即对树进行分层比较。树比对的处理手法是非常“暴力”的,即两棵树只对同一层次的节点进行比较,如果发现节点已经不存在了,则该节点及其子节点会被完全删除掉,不会用于进一步的比较,这就提升了比对效率。


策略二:如果组件的 class 一致,则默认为相似的树结构,否则默认为不同的树结构。(基于组件进行对比)


在组件比对的过程中:


  • 如果组件是同一类型则进行树比对;

  • 如果不是则直接放入补丁中。


只要父组件类型不同,就会被重新渲染。这也就是为什么 shouldComponentUpdate、PureComponent 及 React.memo 可以提高性能的原因。


策略三:同一层级的子节点,可以通过标记 key 的方式进行列表对比。(基于节点进行对比)


元素比对主要发生在同层级中,通过标记节点操作生成补丁。节点操作包含了插入、移动、删除等。其中节点重新排序同时涉及插入、移动、删除三个操作,所以效率消耗最大,此时策略三起到了至关重要的作用。通过标记 key 的方式,React 可以直接移动 DOM 节点,降低内耗。

在调用 setState 之后发生了什么

  • 状态合并,触发调和:

  • setState 函数之后,会将传入的参数对象与当前的状态合并,然后出发调用过程

  • 根据新的状态构建虚拟 dom 树

  • 经过调和过程,react 会高效的根据新的状态构建虚拟 DOM 树,准备渲染整个 UI 页面

  • 计算新老树节点差异,最小化渲染

  • 得倒新的虚拟 DOM 树后,会计算出新老树的节点差异,会根据差异对界面进行最小化渲染

  • 按需更新

  • 在差异话计算中,react 可以相对准确的知道哪些位置发生了改变以及该如何改变,这保证按需更新,而不是宣布重新渲染

hooks 父子传值

父传子在父组件中用useState声明数据 const [ data, setData ] = useState(false)
把数据传递给子组件<Child data={data} />
子组件接收export default function (props) { const { data } = props console.log(data)}子传父子传父可以通过事件方法传值,和父传子有点类似。在父组件中用useState声明数据 const [ data, setData ] = useState(false)
把更新数据的函数传递给子组件<Child setData={setData} />
子组件中触发函数更新数据,就会直接传递给父组件export default function (props) { const { setData } = props setData(true)}如果存在多个层级的数据传递,也可依照此方法依次传递
// 多层级用useContextconst User = () => { // 直接获取,不用回调 const { user, setUser } = useContext(UserContext); return <Avatar user={user} setUser={setUser} />;};
复制代码

Hooks 可以取代 render props 和高阶组件吗?

通常,render props和高阶组件仅渲染一个子组件。React 团队认为,Hooks 是服务此用例的更简单方法。这两种模式仍然有一席之地(例如,一个虚拟的 scroller 组件可能有一个 renderItem prop,或者一个可视化的容器组件可能有它自己的 DOM 结构)。但在大多数情况下,Hooks 就足够了,可以帮助减少树中的嵌套。

React 高阶组件、Render props、hooks 有什么区别,为什么要不断迭代

这三者是目前 react 解决代码复用的主要方式:


  • 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。具体而言,高阶组件是参数为组件,返回值为新组件的函数。

  • render props 是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术,更具体的说,render prop 是一个用于告知组件需要渲染什么内容的函数 prop。

  • 通常,render props 和高阶组件只渲染一个子节点。让 Hook 来服务这个使用场景更加简单。这两种模式仍有用武之地,(例如,一个虚拟滚动条组件或许会有一个 renderltem 属性,或是一个可见的容器组件或许会有它自己的 DOM 结构)。但在大部分场景下,Hook 足够了,并且能够帮助减少嵌套。


(1)HOC 官方解释∶


高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。


简言之,HOC 是一种组件的设计模式,HOC 接受一个组件和额外的参数(如果需要),返回一个新的组件。HOC 是纯函数,没有副作用。


// hoc的定义function withSubscription(WrappedComponent, selectData) {  return class extends React.Component {    constructor(props) {      super(props);      this.state = {        data: selectData(DataSource, props)      };    }    // 一些通用的逻辑处理    render() {      // ... 并使用新数据渲染被包装的组件!      return <WrappedComponent data={this.state.data} {...this.props} />;    }  };
// 使用const BlogPostWithSubscription = withSubscription(BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id));
复制代码


HOC 的优缺点∶


  • 优点∶ 逻辑服用、不影响被包裹组件的内部逻辑。

  • 缺点∶ hoc 传递给被包裹组件的 props 容易和被包裹后的组件重名,进而被覆盖


(2)Render props 官方解释∶


"render prop"是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术


具有 render prop 的组件接受一个返回 React 元素的函数,将 render 的渲染逻辑注入到组件内部。在这里,"render"的命名可以是任何其他有效的标识符。


// DataProvider组件内部的渲染逻辑如下class DataProvider extends React.Components {     state = {    name: 'Tom'  }
render() { return ( <div> <p>共享数据组件自己内部的渲染逻辑</p> { this.props.render(this.state) } </div> ); }}
// 调用方式<DataProvider render={data => ( <h1>Hello {data.name}</h1>)}/>
复制代码


由此可以看到,render props 的优缺点也很明显∶


  • 优点:数据共享、代码复用,将组件内的 state 作为 props 传递给调用者,将渲染逻辑交给调用者。

  • 缺点:无法在 return 语句外访问数据、嵌套写法不够优雅


(3)Hooks 官方解释∶


Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。通过自定义 hook,可以复用代码逻辑。


// 自定义一个获取订阅数据的hookfunction useSubscription() {  const data = DataSource.getComments();  return [data];}// function CommentList(props) {  const {data} = props;  const [subData] = useSubscription();    ...}// 使用<CommentList data='hello' />
复制代码


以上可以看出,hook 解决了 hoc 的 prop 覆盖的问题,同时使用的方式解决了 render props 的嵌套地狱的问题。hook 的优点如下∶


  • 使用直观;

  • 解决 hoc 的 prop 重名问题;

  • 解决 render props 因共享数据 而出现嵌套地狱的问题;

  • 能在 return 之外使用数据的问题。


需要注意的是:hook 只能在组件顶层使用,不可在分支语句中使用。、

哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么?

(1)哪些方法会触发 react 重新渲染?


  • setState()方法被调用


setState 是 React 中最常用的命令,通常情况下,执行 setState 会触发 render。但是这里有个点值得关注,执行 setState 的时候不一定会重新渲染。当 setState 传入 null 时,并不会触发 render。


class App extends React.Component {  state = {    a: 1  };
render() { console.log("render"); return ( <React.Fragement> <p>{this.state.a}</p> <button onClick={() => { this.setState({ a: 1 }); // 这里并没有改变 a 的值 }} > Click me </button> <button onClick={() => this.setState(null)}>setState null</button> <Child /> </React.Fragement> ); }}
复制代码


  • 父组件重新渲染


只要父组件重新渲染了,即使传入子组件的 props 未发生变化,那么子组件也会重新渲染,进而触发 render


(2)重新渲染 render 会做些什么?


  • 会对新旧 VNode 进行对比,也就是我们所说的 Diff 算法。

  • 对新旧两棵树进行一个深度优先遍历,这样每一个节点都会一个标记,在到深度遍历的时候,每遍历到一和个节点,就把该节点和新的节点树进行对比,如果有差异就放到一个对象里面

  • 遍历差异对象,根据差异的类型,根据对应对规则更新 VNode


React 的处理 render 的基本思维模式是每次一有变动就会去重新渲染整个应用。在 Virtual DOM 没有出现之前,最简单的方法就是直接调用 innerHTML。Virtual DOM 厉害的地方并不是说它比直接操作 DOM 快,而是说不管数据怎么变,都会尽量以最小的代价去更新 DOM。React 将 render 函数返回的虚拟 DOM 树与老的进行比较,从而确定 DOM 要不要更新、怎么更新。当 DOM 树很大时,遍历两棵树进行各种比对还是相当耗性能的,特别是在顶层 setState 一个微小的修改,默认会去遍历整棵树。尽管 React 使用高度优化的 Diff 算法,但是这个过程仍然会损耗性能.

对 React context 的理解

在 React 中,数据传递一般使用 props 传递数据,维持单向数据流,这样可以让组件之间的关系变得简单且可预测,但是单项数据流在某些场景中并不适用。单纯一对的父子组件传递并无问题,但要是组件之间层层依赖深入,props 就需要层层传递显然,这样做太繁琐了。


Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。


可以把 context 当做是特定一个组件树内共享的 store,用来做数据传递。简单说就是,当你不想在组件树中通过逐层传递 props 或者 state 的方式来传递数据时,可以使用 Context 来实现跨层级的组件数据传递。


JS 的代码块在执行期间,会创建一个相应的作用域链,这个作用域链记录着运行时 JS 代码块执行期间所能访问的活动对象,包括变量和函数,JS 程序通过作用域链访问到代码块内部或者外部的变量和函数。


假如以 JS 的作用域链作为类比,React 组件提供的 Context 对象其实就好比一个提供给子组件访问的作用域,而 Context 对象的属性可以看成作用域上的活动对象。由于组件 的 Context 由其父节点链上所有组件通 过 getChildContext()返回的 Context 对象组合而成,所以,组件通过 Context 是可以访问到其父组件链上所有节点组件提供的 Context 的属性。

React 最新的⽣命周期是怎样的?

React 16 之后有三个⽣命周期被废弃(但并未删除)


  • componentWillMount

  • componentWillReceiveProps

  • componentWillUpdate


官⽅计划在 17 版本完全删除这三个函数,只保留 UNSAVE_前缀的三个函数,⽬的是为了向下兼容,但是对于开发者⽽⾔应该尽量避免使⽤他们,⽽是使⽤新增的⽣命周期函数替代它们。


⽬前 React16.8+的⽣命周期分为三个阶段,分别是挂载阶段、更新阶段、卸载阶段。


挂载阶段:


  • constructor:构造函数,最先被执⾏,我们通常在构造函数⾥初始化 state 对象或者给⾃定义⽅法绑定 this;

  • getDerivedStateFromProps:static getDerivedStateFromProps(nextProps, prevState),这是个静态⽅法,当我们接收到新的属性想去修改我们 state, 可以使⽤getDerivedStateFromProps

  • render:render 函数是纯函数,只返回需要渲染的东⻄,不应该包含其它的业务逻辑,可以返回原⽣的 DOM、React 组件、Fragment、Portals、字符串和数字、 Boolean 和 null 等内容;

  • componentDidMount:组件装载之后调⽤,此时我们可以获取到 DOM 节点并操作,⽐如对 canvas,svg 的操作,服务器请求,订阅都可以写在这个⾥⾯,但是记得在 componentWillUnmount 中取消订阅;


更新阶段:


  • getDerivedStateFromProps: 此⽅法在更新个挂载阶段都可能会调⽤;

  • shouldComponentUpdate:shouldComponentUpdate(nextProps, nextState),有两个参数 nextProps 和 nextState,表示新的属性和变化之后的 state,返回⼀个布尔值,true 表示会触发重新渲染,false 表示不会触发重新渲染,默认返回 true,我们通常利⽤此⽣命周期来优化 React 程序性能;

  • render:更新阶段也会触发此⽣命周期;

  • getSnapshotBeforeUpdate:getSnapshotBeforeUpdate(prevProps, prevState),这个⽅法在 render 之后,componentDidUpdate 之前调⽤,有两个参数 prevProps 和 prevState,表示之前的属性和之前的 state,这个函数有⼀个返回值,会作为第三个参数传给 componentDidUpdate,如果你不想要返回值,可以返回 null,此⽣命周期必须与 componentDidUpdate 搭配使⽤;

  • componentDidUpdate:componentDidUpdate(prevProps, prevState, snapshot),该⽅法在 getSnapshotBeforeUpdate⽅法之后被调⽤,有三个参数 prevProps,prevState,snapshot,表示之前的 props,之前的 state,和 snapshot。第三个参数是 getSnapshotBeforeUpdate 返回的,如果触发某些回调函数时需要⽤到 DOM 元素的状态,则将对⽐或计算的过程迁移⾄getSnapshotBeforeUpdate,然后在 componentDidUpdate 中统⼀触发回调或更新状态。


卸载阶段:


-componentWillUnmount:当我们的组件被卸载或者销毁了就会调⽤,我们可以在这个函数⾥去清除⼀些定时器,取消⽹络请求,清理⽆效的 DOM 元素等垃圾清理⼯作。


总结:


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

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

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

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

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

  • componentDidUpdate:它主要用于更新 DOM 以响应 props 或 state 更改;

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

setState 之后 发生了什么?

  • (1)代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。

  • (2)经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面;

  • (3)在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染;

  • (4)在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。


setState 的调用会引起 React 的更新生命周期的 4 个函数执行。


shouldComponentUpdate


componentWillUpdate


render


componentDidUpdate

react 实现一个全局的 dialog

import React, { Component } from 'react';import { is, fromJS } from 'immutable';import ReactDOM from 'react-dom';import ReactCSSTransitionGroup from 'react-addons-css-transition-group';import './dialog.css';let defaultState = {  alertStatus:false,  alertTip:"提示",  closeDialog:function(){},  childs:''}class Dialog extends Component{  state = {    ...defaultState  };  // css动画组件设置为目标组件  FirstChild = props => {    const childrenArray = React.Children.toArray(props.children);    return childrenArray[0] || null;  }  //打开弹窗  open =(options)=>{    options = options || {};    options.alertStatus = true;    var props = options.props || {};    var childs = this.renderChildren(props,options.childrens) || '';    console.log(childs);    this.setState({      ...defaultState,      ...options,      childs    })  }  //关闭弹窗  close(){    this.state.closeDialog();    this.setState({      ...defaultState    })  }  renderChildren(props,childrens) {    //遍历所有子组件    var childs = [];    childrens = childrens || [];    var ps = {        ...props,  //给子组件绑定props        _close:this.close  //给子组件也绑定一个关闭弹窗的事件           };    childrens.forEach((currentItem,index) => {        childs.push(React.createElement(            currentItem,            {                ...ps,                key:index            }        ));    })    return childs;  }  shouldComponentUpdate(nextProps, nextState){    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))  }     render(){    return (      <ReactCSSTransitionGroup        component={this.FirstChild}        transitionName='hide'        transitionEnterTimeout={300}        transitionLeaveTimeout={300}>        <div className="dialog-con" style={this.state.alertStatus? {display:'block'}:{display:'none'}}>            {this.state.childs}        </div>      </ReactCSSTransitionGroup>    );  }}let div = document.createElement('div');let props = {   };document.body.appendChild(div);let Box = ReactD
复制代码


子类:


//子类jsximport React, { Component } from 'react';class Child extends Component {    constructor(props){        super(props);        this.state = {date: new Date()};  }  showValue=()=>{    this.props.showValue && this.props.showValue()  }  render() {    return (      <div className="Child">        <div className="content">           Child           <button onClick={this.showValue}>调用父的方法</button>        </div>      </div>    );  }}export default Child;
复制代码


css:


.dialog-con{    position: fixed;    top: 0;    left: 0;    width: 100%;    height: 100%;    background: rgba(0, 0, 0, 0.3);}
复制代码

React 的严格模式如何使用,有什么用处?

StrictMode 是一个用来突出显示应用程序中潜在问题的工具。与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。它为其后代元素触发额外的检查和警告。可以为应用程序的任何部分启用严格模式。例如:


import React from 'react';function ExampleApplication() {  return (    <div>      <Header />      <React.StrictMode>                <div>          <ComponentOne />          <ComponentTwo />        </div>      </React.StrictMode>            <Footer />    </div>  );}
复制代码


在上述的示例中,不会对 HeaderFooter 组件运行严格模式检查。但是,ComponentOneComponentTwo 以及它们的所有后代元素都将进行检查。


StrictMode 目前有助于:


  • 识别不安全的生命周期

  • 关于使用过时字符串 ref API 的警告

  • 关于使用废弃的 findDOMNode 方法的警告

  • 检测意外的副作用

  • 检测过时的 context API

class 类的 key 改了,会发生什么,会执行哪些周期函数?

在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。


答:componentWillMount componentDidMount render

React.forwardRef 有什么用

forwardRef

  • 使用forwardRefforward在这里是「传递」的意思)后,就能跨组件传递ref

  • 在例子中,我们将inputRefForm跨组件传递到MyInput中,并与input产生关联


const MyInput = forwardRef((props, ref) => {  return <input {...props} ref={ref} />;});
function Form() { const inputRef = useRef(null);
function handleClick() { inputRef.current.focus(); }
return ( <> <MyInput ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> );}
复制代码

useImperativeHandle

除了「限制跨组件传递ref」外,还有一种「防止ref失控的措施」,那就是useImperativeHandle,他的逻辑是这样的:既然「ref失控」是由于「使用了不该被使用的 DOM 方法」(比如appendChild),那我可以限制「ref中只存在可以被使用的方法」。用useImperativeHandle修改我们的 MyInput 组件:


const MyInput = forwardRef((props, ref) => {  const realInputRef = useRef(null);  useImperativeHandle(ref, () => ({    focus() {      realInputRef.current.focus();    },  }));  return <input {...props} ref={realInputRef} />;});
复制代码


现在,Form组件中通过inputRef.current只能取到如下数据结构:


{  focus() {    realInputRef.current.focus();  },}
复制代码


就杜绝了「开发者通过ref取到DOM后,执行不该被使用的API,出现ref失控」的情况


  • 为了防止错用/滥用导致ref失控,React 限制「默认情况下,不能跨组件传递ref」

  • 为了破除这种限制,可以使用forwardRef

  • 为了减少refDOM的滥用,可以使用useImperativeHandle限制ref传递的数据结构。

用户头像

beifeng1996

关注

还未添加个人签名 2022.09.01 加入

还未添加个人简介

评论

发布
暂无评论
2022react高频面试题有哪些_前端_beifeng1996_InfoQ写作社区