alibaba / hooks

A high-quality & reliable React Hooks library. https://ahooks.pages.dev/
https://ahooks.js.org/
MIT License
13.95k stars 2.7k forks source link

[Suggestion] Remove life cycle hooks cause they violates the motivation of why React team create hooks. #1438

Closed tianzhich closed 2 years ago

tianzhich commented 2 years ago

Hi the ahooks team, thank you for creating this useful library. I used so many of these hooks in my works which are easy to use and understand. You saved me a lot of time.

But what confused me is why you create life cycle hooks. In our team, some mate like using useMount. Like what they did in class components, the data fetching logic repeats in useEffect and useMount. It makes codes hard to understand and maintain.

You could have a look at the motivation of why React team creates hooks. In which they said:

Each lifecycle method often contains a mix of unrelated logic. For example, components might perform some data fetching in componentDidMount and componentDidUpdate... To solve this, Hooks let you split one component into smaller functions based on what pieces are related (such as setting up a subscription or fetching data), rather than forcing a split based on lifecycle methods.

The react team introduces hooks to avoid the code splitting based on life cycle methods and make developers focused more on business logic. But you bring these life cycle methods back.

IMO If someone likes using these life cycle hooks, he/she may not prepare well to use hooks.


ahook 的开发团队你们好,感谢你们开发了这个有用的库。这里面的 hooks 简单且易于使用,我在工作中大量使用他,这节约了我很多时间。

但我有一个困惑的点就是 LifeCycle hooks。在我团队中有人喜欢使用 useMount。就像他们开发类组件一样,数据获取的逻辑重复在 useEffcet 和这个 useMount 中,这使得代码难以理解和维护。

你们可以看看React 团队开发 hooks 的动机,里面有提到:

每个生命周期往往混合了大量不相关的逻辑。例如,组件在 componentDidMountcomponentDidUpdate 里都有获取数据的逻辑。。。 为了解决这个问题,Hooks 让你可以按相关性(例如事件订阅或者获取数据)把一个组件拆分成一些小的函数块,而不是非得按照生命周期方法来拆分

React 团队创建 hooks 用于避免按照生命周期方法来拆分代码,使得开发者可以更加多地关注业务逻辑。但是你们却把这些生命周期方法又带了回来。

在我看来,如果有人喜欢使用这些生命周期的 hooks,也许说明他还没做好使用 hooks 的准备。

brickspert commented 2 years ago

Technology is innocent, lifecycle functions like useMount and useUnmount are just shorthand for some specific usages of useEffect usage. In engineering projects, using shorthand is definitely more readable than not using shorthand.

Of course, when using it, you need to know what you're doing.

技术是无罪的,useMountuseUnmount 等 生命周期函数,只是对 useEffect 用法的一些特定用法的简写。如果在工程项目中,使用简写肯定比不使用简写具有更强的可读性。

当然,在使用时,你需要知道你在干什么。

useMount(fn) =

useEffect(()=> {
   fn();
}, [])

useUnmount(fn) =

useEffect(() = {
  return () => fn();
}, [])
tianzhich commented 2 years ago

Of course, when using it, you need to know what you're doing.

I think they may not really know what they're doing. The useMount hook hides the fact that the effect should rerun if its dependencies changed by forcing leave its dependencies empty.

This fact is how the react hooks, especially the useEffect hook works. There is no need to use useMount if you use useEffect correctly(for example, use a constant value instead of a variable to empty the dependency array).

brickspert commented 2 years ago

E...... There is no lifecycle, only generic logic encapsulation. In our project, we want to monitor some information when the component is uninstalled, so we need to write frequently

useEffect(() = {
  return() => monitor();
}, [])

Poor readability and a lot of code. Then we simply encapsulate the logic

useUnmount(monitor)

It's such a simple logic, not too many high-rises.

额。没有生命周期,只有通用逻辑封装。在我们的项目中,希望在组件卸载时,需要上报一些信息,那我们就需要频繁的写

useEffect(() = {
  return () => monitor();
}, [])

可读性差,代码量多。那我们就简单封装一下逻辑

useUnmount(monitor)

就是这么简单的逻辑,没有太多的高屋建瓴。

awmleer commented 2 years ago

我并不是喜欢用生命周期的思路去处理,但是在很多情况下,的确是需要写 useEffect(() => {...}, []),我们暂且不去考虑要不要给他扣个生命周期的帽子,就单纯的这样一个 Hooks 的用法,肯定是没有问题的。那么,如果我觉得这种语法有些繁琐、可读性略差,想把它封装一个 custom Hook 出来,那么这个 custom Hook 应该叫啥呢?如果说叫做 useMount 容易误导用户用生命周期的思路去理解 Hooks,那么是不是可以考虑换个名字?

tianzhich commented 2 years ago
useEffect(()=> {
   fn();
}, [])

这样使用当然没有问题,前提是 fn 里没有可变的依赖,但这里相当于把依赖强制为空了,确实是达到了 componentDidMount 的效果,但我认为这样也掩盖了依赖变更,effect 重新执行这一事实。对于 hooks 的初学者知道这个事实是很重要的,但他们可能因为没搞懂这个事实,为了方便就直接使用 useMount

awmleer commented 2 years ago

image

React 官方文档上也是这么描述的啊,感觉不会有啥歧义或者误导性呀:https://reactjs.org/docs/hooks-effect.html

awmleer commented 2 years ago

对于 hooks 的初学者知道这个事实是很重要的,但他们可能因为没搞懂这个事实,为了方便就直接使用 useMount

@tianzhich 反过来想想,如果初学者就是把 useMount 当作 componentDidMount 来用的话,会出现什么问题么?

tianzhich commented 2 years ago

感谢提供上面的截图,但我看到后面还有一段话:

If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often.

所以,如 the props and state inside the effect will always have their initial values 这句话提到,里面也会使用默认值,把它当做 componentDidMount 用也是完全 ok 的。但上面也提到有更好的解决方案去避免 effects 频繁调用(这也是我那个同事使用 useMount 的原因,因为他只想在 didMount 时调用,不知道为什么使用 useEffect 会频繁调用,但却没去寻求上面所说的 better solutions,去发现背后的原因)。

当然,直接去掉也是 breaking change,而且这本身确实没什么问题,我看 react-use 里也有这些 hook。很大程度上受生命周期这个心智模型的影响,不过既然存在上面的问题,还是想抛出来探讨。感谢两位的时间