中级 React 开发人员的坏习惯 事实 个人观点

2025-05-28

中级 React 开发人员的坏习惯

事实

个人意见

如果您是一名中级 React 开发人员,希望成为高级 React 开发人员,那么这篇文章适合您!

几年来,我每天都会审查初级和中级开发人员编写的 React 代码,这篇文章涵盖了我所看到的最常见的错误。我假设你已经了解 React 的基础知识,因此不会讨论像“不要修改 props 或 state”这样的陷阱。

陋习

本节中的每个标题都是您应该避免的坏习惯!

我将使用待办事项列表应用程序的经典示例来说明我的一些观点。

复制状态

每条状态都应该有唯一的真实来源。如果同一条信息在状态中存储两次,则这两个状态可能会不同步。您可以尝试编写代码来同步这两个状态,但这只是一种容易出错的权宜之计,而不是真正的解决方案。

以下是待办事项列表应用中重复状态的示例。我们需要跟踪待办事项列表中的事项以及已完成的事项。您可以在状态中存储两个数组,一个数组包含所有待办事项,另一个数组仅包含已完成的事项:

const [todos, setTodos] = useState<Todo[]>([])
const [completedTodos, setCompletedTodos] = useState<Todo[]>([])
Enter fullscreen mode Exit fullscreen mode

但这段代码往坏了说是 bug 满满,往好了说是臭烘烘的!已完成的待办事项会在 state 中存储两次,所以如果用户编辑了待办事项的文本内容,而你只调用了setTodoscompletedTodos现在返回的仍然是旧的文本,这是错误的!

有几种方法可以删除重复的状态。在这个例子中,你可以简单地completedTodo类型添加一个布尔值,这样completedTodos就不再需要数组了。

Reducer 利用率不足

React 内置了两种存储状态的方式:useStateuseReducer。此外,还有无数用于管理全局状态的库,其中 Redux 最为流行。由于 Redux 通过 Reducer 处理所有状态更新,因此我将使用“Reducer”一词来指代useReducerReducer 和 Redux Reducer。

useState当状态更新简单时,这完全没问题。例如,你可以useState跟踪复选框是否被选中,或者跟踪value文本输入的“”。

话虽如此,当状态更新变得稍微复杂时,你应该使用 Reducer。具体来说,当你在状态中存储数组并且用户可以编辑数组中的每个项目时,都应该使用 Reducer。在我们的待办事项列表应用中,你绝对应该使用 Reducer 来管理待办事项数组,无论是通过 ViauseReducer还是 Redux。

Reducer 是有益的,因为:

  • 它们提供了一个集中的位置来定义状态转换逻辑。
  • 它们非常容易进行单元测试。
  • 它们将复杂的逻辑从组件中移出,从而产生更简单的组件。
  • 如果两个更改同时发生,它们会阻止状态更新被覆盖。传递一个函数setState是另一种防止这种情况的方法。
  • dispatch由于具有稳定的身份,它们能够实现性能优化。
  • 他们允许你使用Immer编写变异风格的代码。你可以将 Immer 与 一起使用useState,但我认为实际上并没有多少人这样做。

没有为容易实现的目标编写单元测试

开发人员非常忙碌,编写自动化测试可能非常耗时。在决定是否应该编写测试时,请问自己:“这个测试是否足够有效,值得我花费时间编写它?” 如果答案是肯定的,那就编写测试吧!

我发现,中级 React 开发人员通常不会编写测试,即使测试只需 5 分钟即可编写,并且影响中等或较高!这些情况就是我所说的测试的“低垂果实”。测试低垂果实吧!

实际上,这意味着要为所有包含重要逻辑的“独立”函数编写单元测试。我所说的“独立”函数指的是定义在 React 组件外部的纯函数。

Reducer 就是一个完美的例子!代码库中任何复杂的 Reducer 都应该拥有接近 100% 的测试覆盖率。我强烈建议使用测试驱动开发 (TDD) 来开发复杂的 Reducer。这意味着你需要为 Reducer 处理的每个 Action 至少编写一个测试,并在编写测试和编写使测试通过的 Reducer 逻辑之间交替进行。

未充分利用React.memouseMemouseCallback

在许多情况下,由 React 提供支持的用户界面可能会变得滞后,特别是当您将频繁的状态更新与渲染成本高的组件配对时(React Select 和 FontAwesome,我正在关注您。)React DevTools 非常适合识别渲染性能问题,无论是使用“组件渲染时突出显示更新”复选框还是使用分析器选项卡。

对抗渲染性能低下最有力的武器是React.memo它仅在组件的 props 发生变化时才重新渲染组件。这里的挑战在于确保 props 不会在每次渲染时都发生变化,否则组件React.memo将不执行任何操作。您需要使用useMemouseCallback钩子来防止这种情况。

我喜欢主动使用React.memouseMemouseCallback来预防性能问题的发生,但被动的方法——即等到发现性能问题后再进行优化——也可以奏效。

useEffect运行频率过高或过低的编写

我对 React Hooks 唯一的抱怨是它useEffect很容易被误用。要成为一名高级 React 开发者,你需要完全理解依赖数组的行为。useEffect

如果你没有使用React Hooks ESLint 插件,你很容易遗漏 effect 的依赖,从而导致 effect 无法按预期运行。这个问题很容易修复——只需使用 ESLint 插件并修复警告即可。

将所有依赖项都列在依赖项数组中后,你可能会发现效果运行过于频繁。例如,效果可能在每次渲染时都运行,从而导致无限更新循环。这个问题没有“一刀切”的解决方案,所以你需要分析具体情况来找出问题所在。我想说的是,如果你的效果依赖于一个函数,那么将该函数存储在 ref 中是一种很有用的模式。就像这样:

const funcRef = useRef(func)

useEffect(() => {
    funcRef.current = func
})

useEffect(() => {
    // do some stuff and then call
    funcRef.current()
}, [/* ... */])
Enter fullscreen mode Exit fullscreen mode

不考虑可用性

作为一名前端开发者,你应该努力成为不仅仅是一名程序员。优秀的前端开发者同时也是可用性和网页设计的专家,即使这些特质并没有体现在他们的职位头衔上。

可用性简单来说就是应用程序的易用性。例如,在列表中添加新的待办事项有多容易?

如果你有机会与真实用户进行可用性测试,那就太棒了。我们大多数人没有这种机会,所以我们必须根据自己对用户友好性的直觉来设计界面。这很大程度上取决于常识,以及观察你每天使用的应用程序中哪些有效,哪些无效。

以下是您今天可以实施的一些简单的可用性最佳实践:

  • cursor: pointer确保可点击元素看起来可点击。将光标移到可点击元素上时,元素的颜色会略微改变,并在 CSS 中变为“指向的手”。将鼠标悬停在 Bootstrap 按钮上,即可查看这些最佳实践的实际效果。
  • 不要隐藏重要的 UI 元素。想象一下,一个待办事项列表应用,当删除待办事项的“X”按钮不可见时,除非你将鼠标悬停在该待办事项上。有些设计师喜欢这种“简洁”的设计,但这需要用户费力寻找才能完成一些基本操作。
  • 用颜色传达含义。显示表单时,使用醒目的颜色来吸引用户对提交按钮的注意!如果有一个永久删除按钮,最好是红色的!不妨看看Bootstrap 的按钮警告框,了解一下。

不努力掌握 CSS 和网页设计

如果你想高效地创建美观的 UI,你必须掌握 CSS 和网页设计。我不指望中级开发人员能够立即创建简洁易用的界面,同时还能保持高效率。学习 CSS 的复杂性并建立对美观的直觉需要时间。但你需要朝着这个方向努力,并随着时间的推移不断进步!

很难给出具体的技巧来提升你的样式设计技巧,但这里有一个:掌握弹性盒子 (flexbox)。虽然弹性盒子一开始可能令人望而生畏,但它是一个功能强大且用途广泛的工具,你可以用它来创建日常开发中所需的几乎所有布局。

以上就是所有坏习惯!看看你是否也犯了这些错误,并努力改进。现在,我将从宏观角度讨论一些可以提升你的 React 代码库的最佳实践。

常规最佳实践

仅使用 TypeScript

普通的 JavaScript 还算可以,但缺乏类型检查,除了小型业余项目外,其他方面都不太适合。用 TypeScript 编写所有代码将极大地提高应用程序的稳定性和可维护性。

如果你觉得 TypeScript 太复杂,那就继续学习吧。一旦你熟练掌握了,你编写 TypeScript 的速度就能和现在编写 JavaScript 一样快。

使用数据获取库

正如我在本文“坏习惯”部分所说,useEffect正确编写 s 非常困难。尤其是在useEffect直接从后端 API 加载数据时。使用一个抽象出数据获取细节的库,可以省去无数的麻烦。我个人更喜欢React Query,不过RTK QuerySWRApollo也是不错的选择。

仅在真正需要时才使用服务器渲染

服务器端渲染 (SSR) 是 React 最酷炫的功能之一。它也极大地增加了应用程序的复杂性。虽然像 Next.js 这样的框架让 SSR 变得更容易,但仍然有一些不可避免的复杂性需要处理。如果您需要 SSR 来实现 SEO 或加快移动设备的加载速度,请务必使用它。但是,如果您正在编写一个没有这些要求的商业应用程序,请使用客户端渲染。您以后会感谢我的。

将样式与组件放在一起

应用程序的 CSS 很快就会变得杂乱无章,无人能理解。Sass 和其他 CSS 预处理器虽然增加了一些实用功能,但仍然在很大程度上存在与原生 CSS 相同的问题。

我认为样式应该限定在单个 React 组件内,并将 CSS 与 React 代码放在一起。我强烈推荐阅读Kent C. Dodds 的精彩博文,了解共置的好处。将 CSS 限定在单个组件内,可以将组件复用作为共享样式的主要方式,并防止样式意外应用于错误元素的问题。

你可以借助Emotionstyled-componentsCSS Modules等类似库来实现组件范围的共置样式。我个人更喜欢使用带有cssprop 的 Emotion。

更新 2022-04-15:澄清了我的声明,即当状态为数组时,应“始终”使用减速器。

文章来源:https://dev.to/srmagura/bad-habits-of-mid-level-react-developers-b41
PREV
逃离 CSS 地狱的 7 种方法 1 和 #6 都写着“text-image: center”,但这不是有效的 CSS。我知道 #1 指的是 text-align,但我不明白 #6 是什么意思……6 应该写 title
NEXT
使用 JWT 处理身份验证