React:我做出了一个违背祖训的决定!

9,510 阅读3分钟

image.png

React 的 useEffect,大家都熟吧?这玩意儿就像个万金油,啥副作用都能往里塞:取数据、搞订阅、手动操作 DOM……反正渲染完了,它帮你擦屁股。它帮你擦屁股。

但是!React 团队最近搞了个大新闻,他们居然要对 useEffect 动刀子了!而且,这次的改动,用他们的话说,简直是——“违背祖训”!“违背祖训”!

useEffect 要变身?实验性 CRUD 支持来了!

新的 useEffect 签名,整合了以前一个实验性的 Hook useResourceEffect 的功能,现在长这样:

function useEffect(
  create: (() => (() => void) | void) | (() => {...} | void | null),
  createDeps: Array<mixed> | void | null,
  update?: ((resource: {...} | void | null) => void) | void,
  updateDeps?: Array<mixed> | void | null,
  destroy?: ((resource: {...} | void | null) => void) | void,
): void

是不是看得一脸懵逼?别慌,我来给你翻译翻译。

以前的 useEffect,创建和清理都挤在一个函数里,跟两口子似的,难舍难分。举个栗子:

useEffect(() => {
  // 创建阶段:发起请求
  const controller = new AbortController();
  fetch('/api/data', { signal: controller.signal })
    .then(response => response.json())
    .then(data => setData(data));

  // 清理阶段:取消请求
  return () => {
    controller.abort();
  };
}, [someDependency]);

看到了吧?创建(发起请求)和清理(取消请求)都得写在一个函数里。

现在好了,React 团队直接把它们拆散了!新签名里,创建、更新、销毁,各司其职,清清楚楚:

  • create: 专门用来造东西(比如,发个请求,整个订阅)。
  • createDeps: create 的跟屁虫,它们一变,create 就得重新执行。
  • update (可选): 想更新?找它!它会拿着 create 造出来的东西,给你更新。
  • updateDeps (可选): update 的小弟,它们一变,update 就得带着老东西,重新来过。
  • destroy: 可选的销毁时候的回调。

“祖宗之法不可变”?React:我就变!

自从 Hook 在 2016 年推出,到现在已经九年了!九年啊!“组合优于继承”、“函数式编程”,这些 React 的“祖训”,各路大神、大V,哪个没给你讲过几百遍?哪个没给你讲过几百遍?

useEffect 把创建和清理揉在一起,也算是“组合”的一种体现,深入人心。可现在呢?React 团队居然亲手把它拆了!这……这简直是自己打自己的脸啊!

不过,话说回来,这种拆分,对于那些复杂的副作用,确实更清晰、更好管理。以前,你可能得在一个 useEffect 里写一堆 if...else,现在,你可以把它们放到不同的阶段,代码更清爽,逻辑更分明。

注意!前方高能预警!

这个 CRUD 功能,现在还是个“试验品”,React 团队还没打算把它放出来。你要是头铁,非要试试,记得先去把 feature flag 打开。不然,你会看到这个:

useEffect CRUD overload is not enabled in this build of React.

重要的事情说三遍:这都是猜的!猜的!猜的!猜的!猜的!猜的!

现在,关于这个新特性,React 团队还没放出任何官方文档或者 RFC。所以,这篇文章,你看看就好,别太当真。它就是基于代码瞎猜的。等官方消息出来了,咱们再好好研究!