React 最佳实践:每位开发者都应该了解的技巧

你好,前端开发爱好者。

随着我对 React 的研究越来越深入,我越来越喜欢这款优秀的前端 JavaScript 库。无需多言,React 是当今最实用和最受开发者欢迎的工具之一。近来,React 团队所做的改进不仅对开发者产生了深远影响,也使得使用 React 构建的应用程序对用户更加友好。

今天,我跟大家分享一些在使用 React 构建应用程序时学到的重要经验,这些经验尤其基于 React Hooks 的使用进行了优化。我们将揭开一些常见的误解,简化常见的概念,并优化你的代码以达到最佳性能。

阅读本文的前提条件是:你必须至少使用过一次 React Hooks,即用 React 开发过一个应用,并运用了 Hooks 的强大功能。这篇文章适合希望充分发挥 React Hooks 潜力的所有人。

React 状态必须是不可变的

你是否想过为什么 React 对不可变性如此执着?作为新手,你可能觉得 JavaScript 的可变性没什么问题,毕竟我们可以轻松地添加或删除对象属性,操作数组。

但在 React 中,不可变性不意味着状态永不改变,而是确保数据的一致性。如果你直接修改状态,React 无法可靠地检测出变化,可能导致 UI 没有按预期更新。正确的做法是用新数据副本替换旧数据。

示例代码:

const updatedUsers = [...users, newUser];
setUsers(updatedUsers);

以上代码使用扩展操作符创建了一个包含新用户的新数组 updatedUsers,而不是直接修改原数组 users。这种方法既确保了 React 的不可变性,也保证了组件的平滑更新。

不要把所有数据都用 useState 管理

曾几何时,我会毫不犹豫地把所有数据都丢进 useState。然而,状态虽然强大,但滥用会导致代码变得复杂和低效。

考虑其他替代方案,例如服务器状态、URL 状态或本地存储。对于服务器数据,可以使用 React Query 等库来处理请求和缓存。对于 URL 状态,可以使用 React Router 的 useLocation 或 Next.js 的内置方法。

在使用 useState 之前,考虑以下几点:

  • 这个值是否可以在渲染时简单派生?
  • 有库已经管理这个状态了吗?
  • 这个值是否需要触发重渲染?

如果这些问题的答案都是“否”,那么你可能不需要 useState

从已有状态中派生值

一个鲜为人知的技巧是:派生值不需要存储在状态中。如果你的数据可以从已有状态或属性中计算出来,直接在渲染时计算它们。

示例代码:

const formattedDate = new Date(date).toLocaleDateString();

以上代码在无需存储的情况下从给定的 date 输入派生出格式化的日期字符串。这种方法避免了不必要的状态管理,简化了渲染逻辑,并保持组件高效。

不要用 useEffect 来计算值

停止使用 useEffect 进行简单的计算!如果你的值可以直接从状态或属性计算出来且不涉及副作用,那就直接在渲染时计算。对于高耗时计算,可以用 useMemo 优化性能:

示例代码:

const expensiveValue = useMemo(() => computeExpensiveValue(data), [data]);

这一做法将使用 useMemo 钩子在 data 变化时重新计算 expensiveValue,避免每次渲染时不必要的重新计算,提升了性能。

keys 应该是唯一的

许多人都有过这样的错误:在列表中使用数组索引作为 key。但这是不好的做法,React 需要唯一的 key 来识别项目,使用非唯一值会导致各种问题。

你可以用 crypto.randomUUID() 生成唯一 ID,但务必要在状态更新时生成,而不是每次渲染时。对于对象,可以考虑添加一个 id 属性:

示例代码:

const itemWithId = items.map(item => ({ ...item, id: generateUniqueId() }));

这样每个项目都会拥有一个唯一的 key,确保 React 能高效地管理更新和渲染列表。

不要遗漏依赖项

React 的一个常见陷阱是:在 useEffect 中遗漏依赖项会导致“过时闭包”(stale closures)。例如,如果你在 useEffect 中没有包含所有需要的依赖项,可能导致效果未按预期更新。

务必仔细检查你的依赖项数组:

示例代码:

useEffect(() => {
  // Effect logic
}, [dependency]);

确保在依赖项数组中包含所有相关的依赖,以保证效果的正确运行,避免遗漏更新造成的潜在问题。

按需使用 useEffect

不要急着使用 useEffect。虽然它很强大,但滥用会导致代码混乱。React 框架提供了更优雅的解决方案来管理副作用。对于数据获取,可以考虑使用 TanStack Query(前身是 React Query)或 SWR 这样的库,它们高效地处理请求和缓存,提升用户体验。

替代策略包括:

  • 直接派生值
  • 使用事件处理器响应事件
  • 在服务器或专门的库中获取数据

示例:如何使用 TanStack Query

import { useQuery } from 'react-query';

const fetchUser = async () => {
  const response = await fetch('https://api.example.com/user');
  if (!response.ok) {
    throw new Error('Network response was not ok');
  }
  return response.json();
};

function User() {
  const { data, error, isLoading } = useQuery('user', fetchUser);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error loading user</div>;

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.email}</p>
    </div>
  );
}

这个示例展示了如何使用 react-query 来处理数据获取。在不使用复杂的 useEffect 和状态管理的情况下,直接通过 useQuery 管理服务器端状态,代码更为简洁和高效。

最后

这篇文章对 React 的一些最佳实践进行了详细阐述,通过多个真实例子帮助你更好地掌握这些技巧,并在实际开发中高效应用。希望这版中文文章能让你更轻松地理解和应用这些知识点。

如果今天的文章有帮到你,希望能够得到一个免费的点赞和关注~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值