内容简介:Everyone’s using React Hooks these days, functions are in and classes are out. No moreBut sadly we’ve traded “cool” for performance, and simple solvable problems likeA problem we rarely had to worry about in the past, but take a simple callback which greet
Everyone’s using React Hooks these days, functions are in and classes are out. No more this
yay! (One of the reasons the React team purportedly introduced them). They allow us to easily “mixin” functionality into our component and elegantly execute code when dependencies change. They’re a nice idea.
But sadly we’ve traded “cool” for performance, and simple solvable problems like this
context for much more nuanced and complicated ones.
Stale memory
A problem we rarely had to worry about in the past, but take a simple callback which greets a person:
If we later change greeting
the callback is now referencing an old value. If this was a 2mb image that would also be a 2mb memory leak. Hooks have introduced one of the two hard things about programming : cache invalidation.
Infinite loops
“Add it as a dependency” the hook experts say. So let’s fetch a random number and set it to state:
Now the fetchRandomNumber
function changes after every fetch and re-runs in an infinite loop.
This seems contrived but happens in any situation where you want to both read and set state in a callback which executes on mount, such as fetching some data when your page loads.
Slower render reconciliation
Most code I’ve seen rarely wraps functional components in React.memo and we’re encouraged to write naked functions inside render which will break any purity checks as they create a new function every render.
We’re told not to prematurely optimize and that it’s probably “fast enough”, because dealing with memoizing all your functions is not pretty, more costly to initialize and execute, and not trivial due to gotchas that require expert knowledge of JavaScript and hooks (we’ll get to this).
When you create methods or variables in classes they are created once per instance . It doesn’t require someone with deep knowledge of JavaScript to combine this with PureComponent to have a very efficiently updating app.
For any callbacks you do handeClick = e => { ... }
and voila you’ve both solved any confusion around this
and also have a “memoized” callback which didn’t involve the nightmares of useCallback
.
And this gain which many people tell you not to worry about really can make a significant difference in large apps or components which render lots of elements like a data grid. In my test on a virtual grid it was over 20x faster to render memoized cells for example.
The useCallback Catch-22
We’ll just use useCallback
you say. So let’s create a resize handle. In a class component the events for mouse would look something like this:
Now let’s do the same for a hook, should be simple right?
I’m sure you’ve spotted a few mistakes, let’s go over them:
- We have a dependency on
attachDocEvents
andremoveDocEvent
in the callbacks - That means we also have to memoize
attachDocEvents
andremoveDocEvents
. Oh and sinceattach/removeDocEvents
reference those callbacks we need to make them dependencies too - Bonus:
useEffect
which is only supposed to be called on unmount will be called every render since theremoveDocEvents
reference changes
All those considerations we didn’t previously have. Let’s try to fix them:
Okay that’s better. But there’s still a problem. Unlike classes or a normal function
, const
functions can only be referenced from top-down. So we cannot reference handleDragMove
or handleDragComplete
before they are defined. But if we move them above then they cannot reference attach/removeDocEvents
. Do you know how to solve that?
Now your average developer who could write an efficient React app with classes needs to be both an expert in Javascript to understand function hoisting and reference passing, and they also need deep domain specific knowledge of React Hooks:
We simply had to “tunnel” in references to the callbacks, lovely! If you knew how to solve this you might think you’re a bonafide useRef
expert. So how about this…
So you think you can useRef
Ms. Hookmeister wants to use a third party physics library for some cool effects. He knows he doesn’t need to re-run it so since he’s a hook expert he uses useRef
instead of useMemo
.
Now particlePhysics
holds a constant reference to the expensive class he just instantiated, and he would be correct.
What he doesn’t know is that even though he always holds the first instance, a new instance is being created every render and discarded . That’s simply the nature of how JS executes. Again, requiring expert understanding to avoid expensive pitfalls.
If you don’t believe me give this a run and check the console:
All this bashing but didn’t I say hooks are a nice idea?
Totally, they can produce some clean looking code. Before hooks we didn’t have such an elegant way to mix in and re-use functionality, and we also saw a lot of ugly code in componentDidUpdate
or getDerivedStateFromProps
to well… derive state from props, but don’t forget that memoization isn’t even a necessity half the time with classes and you can also easily memoize functions and variables in them too.
Hooks are a clever hack to achieve a vision at the expense of API surface area, deeper JS expertise, performance and sometimes complexity. They move the React ecosystem even further away from web standards. Now we are seeing a proliferation of code which can’t even run on one half of React components let alone in a normal JS function.
So are React Hooks the way forward? Let me know what you think!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web 2.0界面设计模式
黄玮 / 电子工业出版社 / 2013-9-1 / 59
本书集Web 2.0的发展及特点、Web 2.0界面设计模式基本理论、实际模式实践及代码实现等诸多内容于一身,具有很强的实用性。这些内容不是简单的顺序堆砌,而是以Web 2.0界面设计模式和应用为主线,其中完美地穿插了各种与之相关的Web 2.0设计理念、用户行为模式、用户体验及基于Dojo的实现方式等相关知识,真正做到将Web 2.0界面设计模式所需要的方方面面的知识有机地融为一个整体。实现不需......一起来看看 《Web 2.0界面设计模式》 这本书的介绍吧!