【手撕面试题】React(高频知识点二)

news2024/11/12 21:27:26

        每天10道题,100天后,搞定所有前端面试的高频知识点,加油!!!在看文章的同时,希望不要直接看答案,先思考一下自己会不会,如果会,自己的答案是什么?想过之后再与答案比对,是不是会更好一点,当然如果你有比我更好的答案,欢迎评论区留言,一起探讨技术之美。

目录

面试官:React的严格模式如何使用?有什么用处?

面试官:请你简述一下useCallBack和useMeno的使用场景

面试官:请你简述一下useEffect的清除机制是什么?在什么时候执行?

面试官:在React为什么调用setState而不是直接改变state?

面试官:React的并发模式是如何执行的?

面试官:简述一下React中setState的第二个参数作用是什么?

面试官:请你简述一下useEffect与useLayoutEffect的区别?

面试官:简述React中key的作用?解决的是哪一类问题?

面试官:简述如何解决props层级过深问题?

面试官:React组件命名推荐的方式是哪个?


面试官:React的严格模式如何使用?有什么用处?

我:呃~,React的严格模式(Strict Mode)是一种用于帮助开发者发现潜在问题的工具,它不会渲染任何UI,而是通过额外的检查来帮助找出可能会导致问题的代码或不推荐的API使用方式,它是在开发模式下运行的,仅在开发环境中有效,对生产环境没有影响。

在React中启用严格模式非常简单,只需要在应用的根组件(通常是index.js 或 App.js)中将整个应用包裹在<React.StrictMode>组件内即可,启用严格模式后React会在开发过程中进行额外的检查,代码如下:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

React严格模式的作用和用处

1)帮助检测不安全的生命周期方法

2)检测意外的副作用,会额外地调用组件的render方法两次

3)启用废弃的 API 检查

4)检测意外的副作用与内存泄漏,如果组件中存在可能导致内存泄漏的副作用会警告开发者

5)帮助提升性能并提供更严谨的代码质量检查

面试官:请你简述一下useCallBack和useMeno的使用场景

我:呃~,它们都是React中的性能优化钩子,帮助开发者在组件渲染时避免不必要的计算和重新创建的操作,目的都是为了优化性能,通过缓存计算结果或者函数避免不必要的重复计算或函数重新创建,以下是它们的详细使用场景:

useCallback:缓存函数,用于避免函数在每次渲染时都被重新创建。它返回的是一个回调函数,只有在依赖项改变时才会更新。

下面这个示例中如果没有useCallback,每次ParentComponent渲染时,handleClick函数都会被重新创建,这会导致ChildComponent不必要的重新渲染,而使用useCallback后,只有在count更新时handleClick才会被更新:

import React, { useState, useCallback } from 'react';

const ChildComponent = React.memo(({ onClick }) => {
  console.log('Child component rendered');
  return <button onClick={onClick}>Click me</button>;
});

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  // 使用 useCallback 确保 onClick 函数只有在 count 更新时才会变化
  const handleClick = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, [count]); // 依赖 count

  return (
    <div>
      <ChildComponent onClick={handleClick} />
      <p>Count: {count}</p>
    </div>
  );
};

export default ParentComponent;

useMemo:缓存值,用于避免在每次渲染时都进行昂贵的计算,它返回一个值,只有当依赖项发生变化时才会重新计算。

在下面这个示例中,expensiveValue只有在count更新时才会重新计算,如果没有useMemo每次父组件重新渲染时,expensiveValue都会重新计算可能会影响性能,尤其是在计算逻辑很复杂时:

import React, { useState, useMemo } from 'react';

const ExpensiveComponent = ({ value }) => {
  console.log('ExpensiveComponent rendered');
  return <div>Computed Value: {value}</div>;
};

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  // 计算一个昂贵的值,只有当 count 更新时才会重新计算
  const expensiveValue = useMemo(() => {
    console.log('Calculating expensive value...');
    return count * 2;
  }, [count]); // 依赖 count

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>Count: {count}</p>
      <ExpensiveComponent value={expensiveValue} />
    </div>
  );
};

export default ParentComponent;

面试官:请你简述一下useEffect的清除机制是什么?在什么时候执行?

我:呃~,useEffect的清除机制是用来清理副作用(side effects)的,例如订阅、计时器、网络请求等,当组件重新渲染或卸载时useEffect可以执行清理操作,它的执行时机有以下两种情况:

1)组件卸载时:useEffect的清理函数在组件卸载时会被调用,用于清理副作用。

2)依赖项变化:useEffect的依赖项数组中的值发生变化,会先执行清理函数再执行新的副作用。

在下面的例子当中,useEffect只会在组件挂载时启动定时器,在组件卸载时返回的清理函数会清除定时器防止内存泄漏:

useEffect(() => {
  // 创建副作用,如订阅或计时器
  const timer = setTimeout(() => {
    console.log('Time’s up!');
  }, 1000);

  // 清除副作用
  return () => {
    clearTimeout(timer); // 清除定时器
  };
}, []); // 空依赖数组表示只在组件挂载和卸载时执行

面试官:在React为什么调用setState而不是直接改变state?

我:呃~,调用setState而不是直接改变state是为了确保组件的状态更新和视图渲染过程符合React的声明式编程模型,具体原因如下:

1)触发重新渲染:React会根据setState调用来决定是否需要重新渲染组件,直接修改state不会触发渲染过程,从而可能导致UI和应用状态不同步。

2)批量更新优化:React使用批量更新机制来优化性能,多个setState调用可能会被合并为一次更新,从而减少不必要的渲染次数,直接修改state则无法利用这一优化。

3)异步更新:setState是异步的,React会在适当的时机更新组件状态,这有助于性能优化并确保正确的更新顺序,直接修改 state 会立即修改状态可能导致不一致的UI和行为。

4)生命周期控制:setState会触发React的生命周期方法(如 componentDidUpdate),帮助开发者在状态更新后执行副作用或进一步操作,直接修改state无法触发这些生命周期方法。

因此,setState是React管理组件状态和确保UI更新的一种关键机制。

面试官:React的并发模式是如何执行的?

我:呃~,React的并发模式(Concurrent Mode)是一种新的渲染模式,旨在提高用户界面的响应性和流畅度,尤其是在处理大型应用和复杂更新时,它通过允许React在后台分配任务来优化渲染过程,使得应用在性能瓶颈处能够更加灵活地进行任务调度从而提升用户体验:

主要特点

1)任务优先级:通过任务的优先级管理来决定哪些渲染任务应该优先执行。

2)可中断渲染:渲染可以是可中断的,这种机制可以避免界面卡顿,提升用户的交互体验。

3)Suspense和Lazy Loading:允许React延迟渲染某些内容,直到它们准备好。

4)自动批处理:允许React自动批处理多个状态更新,减少渲染次数并提升性能。

举例:假设我们有一个大列表它会在用户输入时进行过滤,假设过滤操作非常耗时,如果在输入时直接过滤并渲染整个列表会导致UI卡顿或延迟响应,在并发模式下我们可以将过滤操作作为低优先级任务,在用户输入时通过startTransition来推迟它的执行。

startTransition将更新query标记为低优先级任务,这样即使用户快速输入React也能保证高优先级的任务(如输入响应)优先执行,避免渲染时的卡顿:

import React, { useState, useTransition } from 'react';

function SearchList({ items }) {
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();

  const filteredItems = items.filter(item => item.includes(query));

  const handleChange = (e) => {
    const value = e.target.value;
    startTransition(() => {
      setQuery(value);  // 在低优先级任务中更新查询
    });
  };

  return (
    <div>
      <input value={query} onChange={handleChange} />
      {isPending ? <div>Loading...</div> : null}
      <ul>
        {filteredItems.map(item => <li key={item}>{item}</li>)}
      </ul>
    </div>
  );
}

面试官:简述一下React中setState的第二个参数作用是什么?

我:呃~,setState的第二个参数是一个回调函数,它在状态更新完成后执行,具体来说它在React完成了状态更新并且组件重新渲染之后被调用,其作用如下:

1)访问最新的状态:当希望在状态更新后做一些操作,比如发起网络请求、操作DOM或者更新外部系统等。

2)执行副作用:如果某些副作用操作依赖于组件状态的变化,第二个参数提供了一个钩子,确保状态更新完成后再执行这些操作。

举例:点击按钮时setState更新了count状态,并且第二个参数提供的回调函数会在状态更新完成并且组件重新渲染后执行,输出最新的count值:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    // 更新状态并在状态更新后执行某些操作
    this.setState({ count: this.state.count + 1 }, () => {
      console.log('状态更新完成,最新的 count 值:', this.state.count);
    });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}

面试官:请你简述一下useEffect与useLayoutEffect的区别?

我:呃~,两者都是React Hook,用于在组件的生命周期中执行副作用(side effects)这两者之间的主要区别在于执行时机:

1)useEffect:在浏览器绘制之后执行,当组件渲染(包括虚拟 DOM 更新)完成后React会将副作用任务放到一个队列中等待浏览器绘制(即更新屏幕内容)之后才执行useEffect。

优势在于:避免阻塞页面渲染,因此适用于一些对性能要求不高的副作用,如数据请求或其他非同步操作。

2)useLayoutEffect:在浏览器绘制之前执行,与useEffect相似但它会在React完成DOM更新和布局计算后浏览器开始渲染屏幕之前同步执行,这意味着它会在浏览器绘制之前立即运行,这对于一些需要直接操作DOM或影响布局的副作用非常有用。

优势在于:适用于需要立即修改DOM或做布局调整的操作,因为它会阻止浏览器进行绘制直到副作用完成。

两者的区别如下所示:

特性useEffectuseLayoutEffect
执行时机浏览器绘制完成后执行,即在屏幕渲染后。DOM 更新后,浏览器绘制前执行,即在布局和绘制之前。
常见用途异步操作、数据获取、事件监听等副作用。读取 DOM 属性、布局计算、同步影响布局的操作。
性能影响不会阻塞屏幕渲染,适用于不影响页面渲染的副作用。可能会导致页面渲染延迟,因为它会阻塞浏览器绘制,适用于需要立即修改布局的操作。

使用时机

1)useEffect:大多数副作用都不需要立即影响布局或DOM,尤其是涉及到异步操作、API 请求、事件监听等操作时,应该使用useEffect,它不会阻塞页面渲染,性能上更友好。

2)useLayoutEffect:当需要对DOM或布局进行修改并且这些修改必须在浏览器渲染之前完成时,应该使用useLayoutEffect,例如获取元素尺寸、执行布局调整,或者需要直接控制DOM时。

面试官:简述React中key的作用?解决的是哪一类问题?

我:呃~,key是一个特殊的属性,主要用于帮助React在更新组件时区分哪些元素发生了变化,key解决的问题是列表渲染时的元素重排和性能优化:

key的作用:用来标识组件列表中的每一项确保每个列表项都有一个独特的标识符,React使用key来确定哪些项是新增的、删除的或更改的,从而高效地更新DOM;在渲染列表时会根 key来追踪每个元素的身份,如果没有key或key值不唯一可能会误判哪些元素需要更新,导致不必要的重新渲染,甚至错误的UI状态。

解决问题:主要解决了列表渲染中的重排问题,尤其是当列表项顺序发生变化、删除或新增时准确地识别元素,避免不必要的 DOM 更新。

const items = ['Apple', 'Banana', 'Cherry'];

function FruitList() {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={item}>{item}</li>
      ))}
    </ul>
  );
}

面试官:简述如何解决props层级过深问题?

我:呃~,props层级过深是指组件层级嵌套过多导致需要一层一层地将数据通过props传递给子组件的问题,这种情况会让代码变得冗长难以维护,特别是当 props 深入多层时可能会使得父子组件之间的耦合度过高。

解决props层级过深问题的关键是减少不必要的数据传递,可以通过下面几种方法解决:

1)Context API:简化跨层级传递数据。

2)状态管理库:如 Redux、Recoil 等管理全局状态。

3)组件拆分与重构:提高组件的独立性和复用性。

4)Render Props 和 HOC:分离逻辑,减少层级传递。

5)React Hooks:使用 useContext 和 useReducer 等钩子优化状态管理。

通过这些方式可以有效减少React中因props层级过深而带来的问题,提高应用的可维护性和性能。

面试官:React组件命名推荐的方式是哪个?

我:呃~,组件的命名通常有一些推荐的最佳实践,遵循这些命名规则可以帮助提升代码的可读性、可维护性和一致性,以下是一些 React 组件命名的常见约定和推荐方式:

1)使用 PascalCase 进行组件命名(每个单词首字母大写)。

2)组件文件名通常与组件名相同,使用小写字母和短横线(kebab-case)分隔。

3)根据组件的功能或角色选择合适的前缀或后缀(如 Container、ButtonPrimary 等)。

4)在组合组件时使用有描述性的命名(如 HeaderWithSearch)。

5)保持命名一致性和清晰性,避免使用过于通用的名称(如 App)。

遵循这些命名约定可以确保代码结构清晰、一致,有助于团队协作和代码维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2237166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

若依后端项目打包镜像部署

添加打包依赖 <build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><executi…

使用Python实现音频降噪

在音频处理领域&#xff0c;背景噪声是一个常见的问题。为了提高音频的质量&#xff0c;我们需要对音频进行降噪处理。本文将介绍如何使用 Python 实现音频降噪。 依赖库安装 在开始之前&#xff0c;我们需要安装以下依赖库&#xff1a; pydub&#xff1a;用于音频文件的读取…

18、论文阅读:AOD-Net:一体化除雾网络

AOD-Net: All-in-One Dehazing Network 前言介绍相关工作物理模型传统方法深度学习方法 建模与扩展变换后的公式网络设计与高级特征任务相结合 除雾评价数据集和实现 前言 该论文提出了一种基于卷积神经网络&#xff08;CNN&#xff09;的图像去雾模型&#xff0c;称为 All-in…

软件工程。

图 UML 数据流图&#xff08;DFD&#xff09; 1&#xff0c;数据流图概念 描绘信息流和数据从输入移动到输出的过程中所经受的变换。 也就是 数据流图。 数据流图以图形的方式描绘数据在系统中流动和处理的过程。 数据流图&#xff08;DFD&#xff0c;Data Flow Diagram&a…

机器学习—为什么我们需要激活函数

如果我们使用神经网络中每个神经元的线性激活函数&#xff0c;回想一下这个需求预测示例&#xff0c;如果对所有节点使用线性激活函数&#xff0c;在这个神经网络中&#xff0c;事实证明&#xff0c;这个大神经网络将变得与线性回归没有什么不同&#xff0c;所以这将挫败使用神…

Java基础使用②Java数据变量和类型+小知识点

目录 1. Java小知识点 1.1 Java注释 1.2 Java标识符命名 1.3 Java关键字 2. 字面常量和数据变量 2.1 字面常量 2.2 数据类型 3.变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.4 浮点型变量 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3.8 类型提升 4. 字符…

Blender 几何、线框猴头的构建 笔记

一、学习blender视频教程链接 案例7&#xff1a;猴头构建_建模动画_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Bt4y1E7qn?spm_id_from333.788.videopod.episodes&vd_sourced0ea58f1127eed138a4ba5421c577eb1&p23 二、几何节点基础教程 1.首先添加几何节…

Kafka面试题解答(二)

1.怎么尽可能保证 Kafka 的可靠性 kafka是可能会出现数据丢失问题的&#xff0c;Leader维护了一个动态的in-sync replica set&#xff08;ISR&#xff09;&#xff0c;意为和 Leader保持同步的FollowerLeader集合(leader&#xff1a;0&#xff0c;isr:0,1,2)。 如果Follower长…

用科技力量,重塑数字化园区新生态!

数字化园区的成功打造绝非易事&#xff0c;它需要在多个关键层面付出持之以恒的努力&#xff0c;而成都树莓集团在这一进程中无疑发挥着重要作用。 在数据的管理与应用方面&#xff0c;成都树莓集团更是展现出卓越的实力。集团运用先进的数据挖掘、分析技术&#xff0c;助力园区…

Mac上无法访问usr/local的文件

sudo chmod 755 /usr/loca 最后用百度提供的方法解决了

【Lucene】原理学习路线

基于《Lucene原理与代码分析完整版》&#xff0c;借助chatgpt等大模型&#xff0c;制定了一个系统学习Lucene原理的计划&#xff0c;并将每个阶段的学习内容组织成专栏文章&#xff0c;zero2hero 手搓 Lucene的核心概念和实现细节。 深入的学习和专栏计划&#xff0c;覆盖Lucen…

友思特应用 | 动态捕捉:高光谱相机用于移动产线上的食品检测

导读 高光谱成像技术能够为食品安全助力。以友思特BlackIndustry SWIR 1.7 Max 为代表的高光谱相机&#xff0c;完美解决了移动产线检测的应用难点。 高光谱技术&#xff1a;为食品安全保驾护航 食品安全一直是大众关心的热点话题&#xff0c;提供安全、高质量的食品需要对食…

HarmonyOS使用arkTS拉起指定第三方应用程序

HarmonyOS使用arkTS拉起指定第三方应用程序 前言代码及说明bundleName获取abilityName获取 前言 本篇只说采用startAbility方式拉起第三方应用&#xff0c;需要用到两个必备的参数bundleName&#xff0c;abilityName&#xff0c;本篇就介绍如何获取参数… 代码及说明 bundle…

Linux的基本指令(一)

1.ls指令 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及信息。 常用选项&#xff1a; -a列出目录下的所有文件&#xff0c;包括以 . 开头的隐含文件。 -l列出文件的详细信息 举例&#xff1a; rooti…

基于Springboot+Vue的博客系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

华为OD机试真题-矩形绘制

题目描述 实现一个简单的绘图模块&#xff0c;绘图模块仅支持矩形的绘制和擦除 当新绘制的矩形与之前的图形重善时&#xff0c;对图形取并集 当新擦除的矩形与之前的图形重善时&#xff0c;对图形取差集 给定一系列矩形的绘制和擦除操作&#xff0c;计算最终图形的面积。下…

数据编排与ETL有什么关系?

数据编排作为近期比较有热度的一个话题&#xff0c;讨论度比较高&#xff0c;同时数据编排的出现也暗示着数字化进程的自动化发展。在谈及数据编排时&#xff0c;通常也会谈到ETL&#xff0c;这两个东西有相似点也有不同点。 数据编排和ETL&#xff08;提取、转换、加载&#x…

【Golang】Go语言教程

Go语言教程 文章目录 Go语言教程一、Go语言教程二、Go语言特色三、Go语言用途四、第一个Go程序六、运行代码的两种方式七、go run和go buil的区别7.1、go run7.2、Go build 一、Go语言教程 Go全称Golang Go是一个开源的编程语言&#xff0c;它能让构造简单、可靠且高效的软件变…

【重装系统后重新配置2】pycharm 终端无法激活conda环境

pycharm 终端无法激活 conda 环境&#xff0c;但是 Windows本地终端是可以激活的 原因是pycharm 默认的终端是 Windows PowerShell 解决方法有两个&#xff1a; 一、在设置里&#xff0c;修改为cmd 二、下面直接选择

这是一个bug求助帖子--安装kali 遇坑

第一个报错 介质&#xff1a;kali-linux-2024.1-live-amd64 环境&#xff1a;Dell笔记本 i510代cpu 现象及操作 安装完以后 然后我换了个国内的源进行了以下操作 apt-get update&#xff1a;更新源列表 apt-get upgrade&#xff1a;更新所有可以更新的软件包 然后进行清理。…