创见博客
九坤创新前端面试(2.26 20:00)
七崽爱吃小饼干2026/03/02阅读 1专栏 前端面经

这次面试偏实战。面试官要求不使用ai的情况下,可以通过查找文档创建一个app。

我从React官网查找得到创建React的命令。

Q:面试官提问npx是什么。

过程中碰到了npx create-next-app@latest这样的命令。

npx 是 npm 内置的包执行工具,执行 npx create-next-app@latest 时,它会临时下载最新版的 create-next-app(无需全局安装),直接执行创建 Next.js 项目的命令,执行完就删除临时包。相比传统的全局安装方式,它避免了全局包污染,能始终用最新版本,还简化了操作步骤。

之后我基于vite构建了一个react应用

bash
npm create vite@latest my-app -- --template react

Q:创建好应用后的第一个问题:StrictMode是什么?

jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

一、核心作用

<StrictMode> 包裹整个 App 后,会对所有子组件(包括 App 及其内部所有组件) 生效,在开发环境下触发以下检查和行为:

1. 检测「过时/废弃的 React API」

扫描整个组件树中是否使用了 React 标记为“不安全/废弃”的 API(比如 React.createClass、UNSAFE_componentWillMount、findDOMNode 等),如果有会在控制台抛出明确的警告,提醒你替换为新 API,避免后续升级 React 版本时出现兼容问题。

2. 重复执行「纯函数类逻辑」,暴露非纯函数问题

React 要求组件渲染函数、useState 初始化函数、useMemo/useCallback 回调必须是纯函数(相同输入返回相同输出,无副作用)。StrictMode 会在开发环境下重复执行这些函数两次:

  • 比如你的组件渲染时修改了全局变量、生成随机数(useState(Math.random()))、直接修改 DOM,重复执行后会快速暴露这些非纯逻辑(比如全局变量值异常、随机数两次不一致),强制你规范代码。
  • 注意:这种重复执行仅在开发环境生效,生产环境不会触发,不用担心影响线上功能。

3. 检测「不规范的副作用清理逻辑」

对组件中的 useEffect/useLayoutEffect,StrictMode 会做特殊校验:

  • 首次挂载时:执行副作用函数 → 立即执行清理函数 → 再执行一次副作用函数;
  • 目的是检测你是否规范编写了清理逻辑(比如定时器、事件监听、网络请求取消),避免内存泄漏。
  • 比如你的组件中用 useEffect 开启了定时器但没返回清理函数,StrictMode 会在控制台警告,且开发环境下会出现重复定时器的现象,让你及时发现问题。

4. 检测「违反不可变原则的操作」

比如组件中直接修改 props、state(而非通过 setState/useState 回调修改),或 Context.Provider 的 value 每次渲染都新建对象(导致子组件不必要重渲染),StrictMode 会抛出警告,引导你遵循 React 不可变数据的最佳实践。

二、关键注意点

  1. 仅影响开发环境:生产环境打包后,React 会自动忽略 <StrictMode>,不会有任何额外的检查/重复执行逻辑,也不会带来性能开销;
  2. 开发环境组件渲染两次?正常!:你可能会发现开发环境下组件的 console.log 输出两次,这是 StrictMode 故意重复执行渲染函数导致的,目的就是暴露非纯函数问题,不是 bug;
  3. 全局生效:因为包裹了根组件 <App />,所以整个应用的所有组件都会被 StrictMode 检查,是项目级的全局校验。

三、简化版总结(面试/实操快速回答)

这段代码中 <StrictMode> 的核心作用是:

  1. 在开发环境下对整个应用的组件做全方位的“合规检查”,包括检测废弃 API、非纯函数、不规范的副作用清理、违反不可变原则的操作等;
  2. 提前暴露潜在问题,避免线上 bug;
  3. 生产环境自动失效,无任何性能影响。

简单来说,它就是 React 给开发者的“代码质检员”,只在开发时帮你挑错,上线后就“下班”,是保障项目代码质量的重要手段。

Q: 实现一个倒计时,从100减到0

这个问题的第一个陷阱就是闭包陷阱,如果直接count--,count值就始终会是99。

我这里通过setCount的函数式写法,让setCount从hooks链上直接获取之前的count值。这里也可以用useRef获得一个稳定的引用来解决。

第二个点就是,因为是在严格模式下进行的,所以useEffect会执行两次,会创建两个interval。所以需要卸载interval。否则会出现count一次减2的情况。

第三点在于减到0的时候就需要停止倒计时,也就是需要清除定时器。我这里在precount变成0的时候进行清除。

jsx
import { useEffect, useState } from 'react'
import './App.css'

function App() {
  const [count, setCount] = useState(3)
  useEffect(() => {
    const timer = setInterval(() => {
      setCount((preCount) => {
        if(preCount > 0){
          return preCount - 1
        }else{
          clearInterval(timer)
          return 0
        }
      })
    }, 1000)
    return () => {
      clearInterval(timer)
    }
  }, [])
  return (
    <>
      {count}
    </>
  )
}

export default App

评论
0/100