SuperAPI AI 工具集

react-effects

前端与建站

查看项目

更新于 10-16 22:15

技能介绍

用途

React Effects Guidelines 是一份面向 React 开发者的编码指导规范,主题是何时应该使用 useEffect、何时应该避免使用它。文档以 React 官方文章《你可能不需要 Effect》(https://react.dev/learn/you-might-not-need-an-effect)作为主要参考,目的是减少不必要的 Effect,让组件逻辑更清晰、更易维护。

主要能力

文档提供了一套快速决策树。在添加 useEffect 之前,开发者应依次自问:

  1. 能否在渲染期间计算?→ 直接派生,不要存储后再同步。
  2. 是否只是在 prop 变化时重置状态?→ 改用 key 属性。
  3. 是否由用户事件触发?→ 放到事件处理器中。
  4. 是否在与外部系统同步?→ 此时 Effect 才是合适的。

文档还列出了 Effect 的合理用途:

  • DOM 操作(聚焦、滚动、测量)
  • 外部组件生命周期(终端、图表、非 React 库)
  • 浏览器 API 订阅(ResizeObserver、IntersectionObserver)
  • 挂载或 prop 变化时的数据获取
  • 全局事件监听

使用方式

文档通过反模式与正确写法的代码对比来传达规范。

派生状态:不要用 state 存储再在 Effect 中同步,而应在渲染时直接计算。

// ❌ Derived state stored separately
const [fullName, setFullName] = useState('');
useEffect(() => setFullName(first + ' ' + last), [first, last]);

// ✅ Calculate during render
const fullName = first + ' ' + last;

事件逻辑:不要放在 Effect 中,而应放在事件处理器里。

// ❌ Event logic in effect
useEffect(() => { if (isOpen) doSomething(); }, [isOpen]);

// ✅ In the handler
const handleOpen = () => { setIsOpen(true); doSomething(); };

prop 变化时重置状态:不要用 Effect 重置,而应使用 key。

// ❌ Reset state on prop change
useEffect(() => { setComment(''); }, [userId]);

// ✅ Use key to reset
<Profile userId={userId} key={userId} />

订阅外部数据存储(非 DOM API)时,优先使用 useSyncExternalStore,而不是在 Effect 中手动订阅。

// ❌ Manual subscription in effect
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
  const update = () => setIsOnline(navigator.onLine);
  window.addEventListener('online', update);
  window.addEventListener('offline', update);
  return () => { /* cleanup */ };
}, []);

// ✅ Built-in hook for external stores
const isOnline = useSyncExternalStore(
  subscribe,
  () => navigator.onLine,  // client
  () => true               // server
);

数据获取清理:始终用 ignore 标志处理竞态条件。

useEffect(() => {
  let ignore = false;
  fetchData(query).then(result => {
    if (!ignore) setData(result);
  });
  return () => { ignore = true; };
}, [query]);

应用初始化:对于每次应用加载只执行一次(而非每次挂载一次)的逻辑,使用模块级守卫。

let didInit = false;

function App() {
  useEffect(() => {
    if (!didInit) {
      didInit = true;
      loadDataFromLocalStorage();
      checkAuthToken();
    }
  }, []);
}

或者在模块初始化阶段(渲染前)执行:

if (typeof window !== 'undefined') {
  checkAuthToken();
  loadDataFromLocalStorage();
}

适用场景

该规范适用于所有使用 React 函数组件与 Hooks 的前端开发场景,尤其适合需要审查或重构 Effect 用法的团队,以及希望遵循 React 官方推荐实践的开发者。

限制

资料未提供该规范的版本、许可、安装方式、依赖要求或平台限制等信息,暂未提供。