关于react.js:百度前端高频react面试题总结

3次阅读

共计 6205 个字符,预计需要花费 16 分钟才能阅读完成。

能够应用 TypeScript 写 React 利用吗?怎么操作?

(1)如果还未创立 Create React App 我的项目

  • 间接创立一个具备 typescript 的 Create React App 我的项目:
 npx create-react-app demo --typescript

(2)如果曾经创立了 Create React App 我的项目,须要将 typescript 引入到已有我的项目中

  • 通过命令将 typescript 引入我的项目:
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
  • 将我的项目中任何 后缀名为‘.js’的 JavaScript 文件重命名为 TypeScript 文件即后缀名为‘.tsx’(例如 src/index.js 重命名为 src/index.tsx)

pureComponent 和 FunctionComponent 区别

PureComponentComponent 完全相同,然而在 shouldComponentUpdate 实现中,PureComponent应用了 propsstate的浅比拟。次要作用是用来进步某些特定场景的性能

什么是 React Fiber?

Fiber 是 React 16 中新的协调引擎或从新实现外围算法。它的次要指标是反对虚构 DOM 的增量渲染。React Fiber 的指标是进步其在动画、布局、手势、暂停、停止或重用等方面的适用性,并为不同类型的更新调配优先级,以及新的并发原语。
React Fiber 的指标是加强其在动画、布局和手势等畛域的适用性。它的次要个性是增量渲染: 可能将渲染工作宰割成块,并将其扩散到多个帧中。

React 父组件如何调用子组件中的办法?

  1. 如果是在办法组件中调用子组件(>= [email protected]),能够应用 useRef 和 useImperativeHandle:
const {forwardRef, useRef, useImperativeHandle} = React;

const Child = forwardRef((props, ref) => {useImperativeHandle(ref, () => ({getAlert() {alert("getAlert from Child");
    }
  }));
  return <h1>Hi</h1>;
});

const Parent = () => {const childRef = useRef();
  return (
    <div>
      <Child ref={childRef} />
      <button onClick={() => childRef.current.getAlert()}>Click</button>
    </div>
  );
};
  1. 如果是在类组件中调用子组件(>= [email protected]),能够应用 createRef:
const {Component} = React;

class Parent extends Component {constructor(props) {super(props);
    this.child = React.createRef();}

  onClick = () => {this.child.current.getAlert();
  };

  render() {
    return (
      <div>
        <Child ref={this.child} />
        <button onClick={this.onClick}>Click</button>
      </div>
    );
  }
}

class Child extends Component {getAlert() {alert('getAlert from Child');
  }

  render() {return <h1>Hello</h1>;}
}

diff 算法是怎么运作

每一种节点类型有本人的属性,也就是 prop,每次进行 diff 的时候,react 会先比拟该节点类型,如果节点类型不一样,那么 react 会间接删除该节点,而后间接创立新的节点插入到其中,如果节点类型一样,那么会比拟 prop 是否有更新,如果有 prop 不一样,那么 react 会断定该节点有更新,那么重渲染该节点,而后在对其子节点进行比拟,一层一层往下,直到没有子节点

这段代码有什么问题吗?

这段代码有什么问题:

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

答案:
没有什么问题。这种形式很少被应用,咱们能够将一个函数传递给setState,该函数接管上一个 state 的值和以后的props,并返回一个新的状态,如果咱们须要依据以前的状态从新设置状态,举荐应用这种形式。

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 干嘛用的?

... 在 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"} };
});

什么是 prop drilling,如何防止?

在构建 React 应用程序时,在多层嵌套组件来应用另一个嵌套组件提供的数据。最简略的办法是将一个 prop 从每个组件一层层的传递上来,从源组件传递到深层嵌套组件,这叫做 prop drilling
prop drilling 的次要毛病是本来不须要数据的组件变得不必要地简单,并且难以保护。
为了防止 prop drilling,一种罕用的办法是应用React Context。通过定义提供数据的Provider 组件,并容许嵌套的组件通过 Consumer 组件或useContext Hook 应用上下文数据。

参考:前端 react 面试题具体解答

React 如何判断什么时候从新渲染组件?

组件状态的扭转能够因为 props 的扭转,或者间接通过 setState 办法扭转。组件取得新的状态,而后 React 决定是否应该从新渲染组件。只有组件的 state 发生变化,React 就会对组件进行从新渲染。这是因为 React 中的 shouldComponentUpdate 办法默认返回true,这就是导致每次更新都从新渲染的起因。

当 React 将要渲染组件时会执行 shouldComponentUpdate 办法来看它是否返回 true(组件应该更新,也就是从新渲染)。所以须要重写shouldComponentUpdate 办法让它依据状况返回 true 或者 false 来通知 React 什么时候从新渲染什么时候跳过从新渲染。

什么是纯函数?

纯函数是不依赖并且不会在其作用域之外批改变量状态的函数。实质上,纯函数始终在给定雷同参数的状况下返回雷同后果。

React 如何获取组件对应的 DOM 元素?

能够用 ref 来获取某个子节点的实例,而后通过以后 class 组件实例的一些特定属性来间接获取子节点实例。ref 有三种实现办法:

  • 字符串格局:字符串格局,这是 React16 版本之前用得最多的,例如:<p ref="info">span</p>
  • 函数格局:ref 对应一个办法,该办法有一个参数,也就是对应的节点实例,例如:<p ref={ele => this.info = ele}></p>
  • createRef 办法 :React 16 提供的一个 API,应用 React.createRef() 来实现

在 React 中组件的 this.state 和 setState 有什么区别?

this.state 通常是用来初始化 state 的,this.setState 是用来批改 state 值的。如果初始化了 state 之后再应用 this.state,之前的 state 会被笼罩掉,如果应用 this.setState,只会替换掉相应的 state 值。所以,如果想要批改 state 的值,就须要应用 setState,而不能间接批改 state,间接批改 state 之后页面是不会更新的。

什么是虚构 DOM?

虚构 DOM (VDOM)是实在 DOM 在内存中的示意。UI 的示意模式保留在内存中,并与理论的 DOM 同步。这是一个产生在渲染函数被调用和元素在屏幕上显示之间的步骤,整个过程被称为 和谐。

s# 如何防止在 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>
  );
};

何为 Children

在 JSX 表达式中,一个开始标签 (比方<a>) 和一个敞开标签 (比方</a>) 之间的内容会作为一个非凡的属性 props.children 被主动传递给蕴含着它的组件。

这个属性有许多可用的办法,包含 React.Children.mapReact.Children.forEachReact.Children.countReact.Children.onlyReact.Children.toArray

React 16.X 中 props 扭转后在哪个生命周期中解决

在 getDerivedStateFromProps 中进行解决。

这个生命周期函数是为了代替 componentWillReceiveProps 存在的,所以在须要应用 componentWillReceiveProps 时,就能够思考应用 getDerivedStateFromProps 来进行代替。

两者的参数是不雷同的,而 getDerivedStateFromProps 是一个动态函数,也就是这个函数不能通过 this 拜访到 class 的属性,也并不举荐间接拜访属性。而是应该通过参数提供的 nextProps 以及 prevState 来进行判断,依据新传入的 props 来映射到 state。

须要留神的是,如果 props 传入的内容不须要影响到你的 state,那么就须要返回一个 null,这个返回值是必须的,所以尽量将其写到函数的开端:

static getDerivedStateFromProps(nextProps, prevState) {const {type} = nextProps;
    // 当传入的 type 发生变化的时候,更新 state
    if (type !== prevState.type) {
        return {type,};
    }
    // 否则,对于 state 不进行任何操作
    return null;
}

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

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

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

什么起因会促使你脱离 create-react-app 的依赖

当你想去配置 webpack 或 babel presets。

传入 setState 函数的第二个参数的作用是什么?

该函数会在 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}
})
正文完
 0