oakland / tecblog

My tech blogs
4 stars 0 forks source link

React Hooks #165

Open oakland opened 5 years ago

oakland commented 5 years ago

前言

最近打算做一个 react 的分享,可以分享的点挺多的,但是因为是 hooks 刚出来不久,所以就打算分享 hooks。看了一点官方文档,都是用法相关的,所以就想知道为什么会出现 hook 这个概念,这个概念到底是为了解决什么问题而出现的。问了 reactjs 小书群里的朋友,给了 make sense of react hooks 这篇文章,觉得写得不错。先把一些点记录下来。

最近还需要看的文章

react-hooks-not-magic-just-arrays

摘录和自己的想法

首先,第一感觉是 hook 确实减少了 react 的代码量。其次就是 hook 感觉可以消灭掉很多概念,比如 HOC, render props, context, this(不用关心 this 是通过将 class component 修改成 function component 的方式实现的,不用再通过 this.xxx = this.xxx.bind(this) 来绑定 this 了) 等等。但是之前为什么会出现上面说的这些概念,而 hook 为什么又要消灭这些概念。还需要重新认识一下上面的概念。包括还有 mixin 和 recompose 这些概念,等等。

下面这句话解释了 HOC 和 render props 出现的原因。带着这个解读再去看看 react 官方文档对于这两个概念的解释。

Components are more powerful, but they have to render some UI. This makes them inconvenient for sharing non-visual logic. This is how we end up with complex patterns like render props and higher-order components.

就是说 HOC 和 render props 都是为了解决非 ui 相关的逻辑出现的。

hook 的官方文档中有下面这样一段话

Sometimes, we want to reuse some stateful logic between components. Traditionally, there were two popular solutions to this problem: higher-order components and render props. Custom Hooks let you do this, but without adding more components to your tree.

可以能感觉到 hook 想要解决的问题,和 hoc 和 render props 尝试要解决的问题,通过不同的方式来书写?

官方文档中还有这样一段话,值得仔细品味

Hooks are a way to reuse stateful logic, not state itself.

show me some code 这个部分中,举了一个 useWindowWidth 的例子,感觉这个就是把很多逻辑解耦了。比如 useWindowWidth 这个 hook 就可以用在多个不同的 components 上。而不像原来为了复用这个必须要创建一个 HOC。其实感觉这个的出现还是为了解耦和提高复用率。

关于 side effect

side effect 的意思其实一直没有很好的理解,react 官方文档中有这样一段话,有助于理解这个意思:

You’ve likely performed data fetching, subscriptions, or manually changing the DOM from React components before. We call these operations “side effects” (or “effects” for short) because they can affect other components and can’t be done during rendering.

到底什么是 hook

官方文档在 useState hook 中给出了如下的解释

What is a Hook? A Hook is a special function that lets you “hook into” React features. For example, useState is a Hook that lets you add React state to function components. We’ll learn other Hooks later.

When would I use a Hook? If you write a function component and realize you need to add some state to it, previously you had to convert it to a class. Now you can use a Hook inside the existing function component. We’re going to do that right now!

下面一段话来自官方文档的 useEffect,对于理解什么是 side effect 有帮助,表示渲染 ui 之外的事情?

In React class components, the render method itself shouldn’t cause side effects. It would be too early — we typically want to perform our effects after React has updated the DOM. This is why in React classes, we put side effects into componentDidMount and componentDidUpdate.

useEffect 的另外一种使用方式,就是把本来应该有关联的内容写在一起,比如 订阅和取消订阅 的功能。

You might be thinking that we’d need a separate effect to perform the cleanup. But code for adding and removing a subscription is so tightly related that useEffect is designed to keep it together. If your effect returns a function, React will run it when it is time to clean up:

Instead, we’d like to share this logic between FriendStatus and FriendListItem. Traditionally in React, we’ve had two popular ways to share stateful logic between components: render props and higher-order components. We will now look at how Hooks solve many of the same problems without forcing you to add more components to the tree.

使用 hooks 可以 share logic,共享组件逻辑。没有 hooks 之前这种共享的方式是通过 hoc 和 render props 来实现的。

higher order components 导致的问题之一就是 component hell,各种 component wrapper 来实现某个功能,而是用 hooks 的话可以减少组件嵌套,拍平组件。

参考资料

oakland commented 3 years ago

最近要重写项目了,原来项目的用法还是老的 react 用法。很多内容都重构了,现在再回头来看看 react hooks 相关的内容,为做出更优化的前端项目而努力。

下面这篇文章值得多看几遍,一定要多看几遍,看懂看透。而且里面的评论也很精彩。有些评论中的文章是很好的。其中有一篇文章点出了,貌似 react hooks 的前身是 recompose。 https://juejin.cn/post/6844903813070094350#heading-8

如果你希望有一个新的分页结构与样式,那就重写一个结构,并引用 usePagination 。总之,最核心的状态处理逻辑已经被我们抽离出来,因为无关this,于是它与组件无关、与dom也可以无关。爱插哪插哪,谁爱用谁用。百花丛中过,片叶不沾身。 这么一来,数据层与dom更加的分离,react组件更加的退化成一层UI层,进而更易阅读、维护、拓展。

这里很好的解释了 hooks 出现的原因,就是 hooks 让组件的逻辑和样式更加剥离开,解耦。实现逻辑的复用,不只是样式的复用。实际上这个时候 hooks 的颗粒度大小和组件的颗粒度大小也成为我们作为开发者要关注的重点之一了。

oakland commented 3 years ago

这篇文章中列举了同样一个场景用 hoc, render props 和 hooks 这三种不同的方式来写。 实际上能看的出 hooks 的写法更加简洁,可读性也更强。虽然场景简单,但是却能很好的展现出 hooks 的魅力。 我的理解就是把 view 和 data 还有 logic 彻底解耦,也就是说 view 单纯的展示界面了,而如何获取数据还有对数据做如何的处理实际上完全交给 hooks 了。我现在为什么对 hooks 的理解还不够,或者说没有深刻的感受到 hooks 的魅力,可能就是因为平时逻辑和数据复用的场景太少了,所以没法体会到 hooks 的好处。后面的开发还是要在实践中去理解,能用 Hooks 的就尽量用 hooks。

oakland commented 3 years ago

https://www.youtube.com/watch?v=dpw9EHDh2bM&feature=youtu.be&ab_channel=ReactConf

image

image

深入去研究一下 react dev tools 和 profiler 也可能是值得的,因为这里面也会隐藏一些 react 相关的内容,通过这些工具的使用可以让你对 react 有一些独特的视角观点。

what react sucks

  1. reusing logic( higher order component and render props), hoc and render props may be good, but some times they lead to wrapper hell
  2. giant components
  3. confusing classes
oakland commented 3 years ago

deep-dive-how-do-react-hooks-really-work

上面这篇文章是很不错的,

Hooks are a fundamentally simpler way to encapsulate stateful behavior and side effects in user interfaces.

关于这句话,我突然想到,其实闭包就是一个带有作用域的函数,而现在的 functional component 其实也是个函数而已,所以 useState 其实就是通过闭包的形式给这个函数添加上一个作用域而已。所以为什么好多文章都在把 hooks 和 闭包 联系起来,就是这个原因吧。