首页 react面试题
文章
取消

react面试题

函数组件和 class 组件的区别

  • 纯函数,输入 props,输出 JSX
  • 没有实例,没有生命周期,没有 state
  • 不能扩展其他方法

什么是受控组件?

  • 表单的值受 state 控制(状态驱动视图)
  • 需要自行监听 onChange, 更新 state

何时使用异步组件

  • 加载大组件
  • 路由懒加载

多个组件有公共逻辑,如何抽离

  • 高阶组件(HOC)
  • Render Props
  • mixin 已经被 React 废弃

redux 如何进行异步请求

  • 使用异步 action
  • redux-thunk

react-router 如何配置懒加载

  • lazy(()=> import('component'))
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
    import React, { Suspense, lazy } from 'react';
    const Home = lazy(() => import('./routes/Home'));
    const About = lazy(() = import('-/routes/About'));
    const App = () => (
      <Router>
          <React.Suspense fallback={<div>loading</div>}> 
              <Switch>
                  <Router exact path="/" component={Home}/>
                  <Route path="/about" component={About}/>
              </Switch>
          </React.Suspense>
      </Router>
    );
    

React.PureComponent作用

  • 实现浅比较的 shouldComponentUpdate
  • 性能优化
  • 要结合不可变值使用

React 事件和 DOM 事件的区别

  • 所有事件挂载到了 document
  • event 不是原生的,是 SyntheticEvent 合成事件对象
  • dispatchEventdispatchEvent 方法接受一个事件对象作为参数,并在DOM元素上触发该事件)

React 性能优化

  • 渲染列表是加 key
  • 自定义事件、DOM 事件及时销毁
  • 合理使用异步组件
  • 减少函数 bind this 的参数
  • 合理使用 SCU PureComponentmemo
  • 合理使用 Immutable.js
  • 通用的性能优化,如图片懒加载

React 和 Vue 的区别

不同点:

  • React 使用 JSX 拥抱 JS, Vue 使用模版拥抱 html
  • React 函数式编程,Vue 生明式编程
  • React 更多需要自力更生, Vue 把想要的都给你

相同点:

  • 都支持组件化
  • 都是数据驱动视图
  • 都使用 vdom 操作 DOM

React Hooks 性能优化

  • useMemo 缓存数据
  • useCallback 缓存函数

    useMemo useCallback 相当于 class 组件中的 SCUPureComponent

React Hooks 遇到哪些坑

  • useState 初始化值只能初始化一次
    • render:初始化 state
    • re-render:只恢复初始化的 state 值,不会再重新设置新的值,想要修改 只能使用 setState 修改
  • useEffect 内部不能修改 state (解决方案推荐使用 useRef()
  • useEffect 依赖引用类型,会出现死循环(原理是:依赖项的比较是通过 Object.is({}, {}) 进行比较,当前两个对象比较返回的是 false, 如果是值类型会对比值的是否相同)

React Hooks 做组件逻辑复用的点

  • 完全符合 Hooks 原有规则,没有其他要求,易理解记忆
  • 变量作用域很明确
  • 不会产生组件嵌套的问题

JSX 本质

  • React.createElementh 函数,返回 vnode,然后通过 patch 进行处理渲染
  • 第一个参数可能是组件,也可能是 html tag标签。(区分组件与html写法是根据首字母的大小写,组件规定要首字母大小,html标签都是小写)
  • 组件名称首字母必须大写(React 规定)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
      // JSX 语法
      const listElem = <div>
          <Input submitTitle={onSubmitTitle}/>
          <List list={list}/>
      </div>
    
      // 转化为`React.createElement`
      // const listElem = React.createElement("div", null, React.createElement(Input, {
      //         submitTitle: onSubmitTitle
      //     }), React.createElement(List, {
      //     list: list
      // }));
    

子组件暴漏方法给父组件调用

  • React.forwardRef 提供了一个强大的方法在组件中传递 ref , forwardRef 将父组件创建的 ref 引用关联到子组件中任意元素
  • useImperativeHandle 定义要在组件中暴漏的数据和自定义方法,此方法接受两个参数: ref 和一个回调函数,回调函数返回一个对象(由父组件定义的 ref 直接调用当前子组件件暴漏的方法)

使用代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 子组件 ChildComponent.js
import React, { forwardRef, useImperativeHandle } from 'react';

const ChildComponent = forwardRef((props, ref) => {
  const internalMethod = () => {
    console.log("Internal method called in child component");
    // 这里可以是子组件内部的逻辑
  };

  // 将自定义方法暴露给父组件
  useImperativeHandle(ref, () => ({
    callInternalMethod: internalMethod
  }));

  return (
    <div>
      {/* 子组件的其他内容 */}
    </div>
  );
});

export default ChildComponent;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 父组件 ParentComponent.js
import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  // 创建一个 ref
  const childRef = useRef();

  // 在父组件中调用子组件的自定义方法
  const handleButtonClick = () => {
    if (childRef.current) {
      childRef.current.callInternalMethod();
    }
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleButtonClick}>Call Child Method</button>
    </div>
  );
};

export default ParentComponent;

class component 使用 refReact.createRef() 子类组件被调用自定义方法时,默认自定义方法就可以被父组件直接调用

fiber

fiber出现的背景,性能解决:

  • js 是单线程,且和 DOM 渲染共用一个线程
  • 当组件足够复杂,组件更新时计算和渲染压力大
  • DOM 操作需求(动画,鼠标拖拽)出现页面卡顿
  • reconciliation 阶段进行任务拆分(commit 无法拆分)
  • DOM 需要渲染时暂停,空闲时恢复 (DOM 什么时候需要渲染是通过 window.requestIdleCallback )

fiberreact 核心算法的一次重新实现,将原本同步的更新过程碎片化,避免主线程长时间的阻塞。

利用分片的思想,将耗时任务分成很多小片,每个小片执行完之后,把控制权交给 react 负责协调的模块,如果有紧急任务就优先处理,没有就继续更新。

一个更新过程,两个阶段:

第一阶段:找出需要更新的 DOM,这个阶段是可以被打断的 第二阶段:完成 DOM 的更新展示,这个阶段是不可以被打断的

useEffect 闭包陷阱

  • React Hooks useEffect 闭包陷阱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function useEffectDemo() {
  const [value, setValue] = useState(0)
  useEffect(() => {
    setInterval(() => {console.log(value)}, 1000)
  }, [])
  function clickHandler() {
    setValue(value+1)
  }
  return (
    <div>
      value: {value} <button onClick={clickHandler}>increase</button>
    </div>
  )
}

// 输出结果为 0

useEffect 依赖项为空数组时它只会执行一次 console.log(value) 获取的永远是一次渲染时初始化的 state 值,value 发生变更时重新执行渲染

react 18 新特性

React 18的新特性包括:

  1. 并发渲染:React 18引入了并发渲染,这是一种新的后台机制,使React能够同时准备多个版本的UI¹²。并发渲染允许React在执行重渲染任务的过程中快速响应用户交互¹。

  2. 自动批处理:React 18引入了自动批处理,这是一种性能改进,可以使用户界面开发过程更加流畅和响应¹²。

  3. 新的API:React 18引入了一些新的API,如createRoot, hydrateRoot, renderToPipeableStream, renderToReadableStream,以及一些新的Hooks,如useId, useTransition, useDeferredValue, useSyncExternalStore, useInsertionEffect¹。

  4. 过渡:React 18引入了startTransition API,这是一种新的API,可以帮助你保持应用的响应性¹²。

  5. 服务端的Suspense:React 18引入了服务端的Suspense,这是一种新的架构改进,可以提高渲染性能¹²。

  6. 严格模式:在React 18中,ReactDOM.renderrenderToString被弃用¹。

使用createRoot代替render。在你的index.js中,将ReactDOM.render更新为ReactDOM.createRoot来创建一个root,并使用root渲染你的应用¹。

fibar 与 react18 并发渲染 区别

React 18的并发渲染React Fiber是两个不同的概念,但它们都是React的核心部分,用于优化UI的渲染。

React Fiber是 React 的核心算法的重新实现。Fiber 引入了一种新的调度机制,将渲染工作分解成更小的单元(称为“Fiber”),并根据其重要性为每个 Fiber 分配优先级³。高优先级的 Fiber(如用户输入和动画)会被优先处理,而低优先级的Fiber(如离屏更新)会被推迟处理,直到浏览器有空闲时间³。

React 18的并发渲染则是建立在Fiber基础之上的一种新的渲染模式。并发渲染允许 React 在执行重渲染任务的过程中快速响应用户交互。这是通过让渲染变得可中断来实现的:React 可以中断、暂停、恢复或放弃渲染。这种模式使得 React 可以同时准备多个版本的UI。

总的来说,React Fiber 是React的底层架构,用于优化渲染的调度,而React 18的并发渲染则是在此基础上,通过允许渲染的中断和恢复,来进一步提升应用的响应性和性能

useReducer 和 redux 的区别

  • useReduceruseState 的代替方案,用于 state复杂变化
  • useReducer 是单个组件状态管理,组件通讯还需要 props
  • redux 是全局的状态管理,多组件共享数据

为什么要使用 Hooks

  • 完善函数组件的能力,函数更适合 React 组件
  • 组件逻辑复用,Hooks 表现更好
  • 更好的状态管理,Hooks 可以更好的管理组件状态
转摘分享请注明出处

浏览器输入url发生了什么

vue常见考题