34 ms·
Understanding UseMemo and UseCallback
- adamredwoods 4y agoDon't forget there are other paradigms out there! https://www.solidjs.com/guides/reactivity https://www.solidjs.com/guides/reactivity
- GenerocUsername 4y agoNothing wrong with this blog but I'm pretty sure the exact title has been done 1000x
- lucasmullens 4y agoI Googled "Understanding UseMemo and UseCallback" and there were 7 results, all referencing this exact article.
- cercatrova 4y agoI always enjoy Comeau's blog posts, they're the essence of interactive learning. For real world things, I also like Bartosz Ciechanowski's work [0], they have very highly detailed renditions of things like mechanical watches and internal combustion engines. [0] https://ciechanow.ski/ https://ciechanow.ski/
- johnny_reilly 4y agoI love the way this is put together. Just outstanding work - totally readable with interactive illustrations. Hats off!
- latchkey 4y agoHis previous one on rerenders was fantastic... many lightbulb moments. https://www.joshwcomeau.com/react/why-react-re-renders/ https://www.joshwcomeau.com/react/why-react-re-renders/ FB should hire him to rewrite their docs.
- andy_ppp 4y agoThis is really excellent. I have a hook that is producing updated data every second, it’s pretty annoying that this causes everything below where the hook was included to be re-rendered each time, even if the updated data isn’t included. I can’t help but think using redux and connecting components to a global store as far down the hierarchy as possible was much more efficient. Is there an alternative way to do this with hooks to avoid re-rendering? One thing I’ve started doing everywhere is putting a logger.debug(“rendering WidgetX”) at the top of every component to catch anything weird as I go along, it’s been pretty helpful.
- encoderer 4y agoPush the hook down to the lower components, and use it like you would redux?
- andy_ppp 4y agoBut I need things the hook does elsewhere, as I say I’m not even using the stuff that updates in the main component… Maybe I can separate the hooks into sets the data and reads the data somehow… Might just return to redux to be honest for this bit at least…
- ummonk 4y agoYeah separating out sets and reads is one of the reasons Redux exists.
- patrickthebold 4y agoYou can use React.useMemo to prevent children from rerendering when passed the same props. I'm not 100% sure if that's what you are describing.
- aarpmcgee 4y agofrom the article: "So, to go back to our misconception: props have nothing to do with re-renders."
- moltar 4y agoReally nice, but works badly on mobile with a small screen.
- telman17 4y agoI love Josh's writeups. His CSS for JS devs course is also fantastic for folks who want to get better at CSS.
- continuational 4y agoOnce you add useMemo and useCallback, your code will become pretty unsightly though. I wish React had a better solution to this problem.
- gedy 4y agoAgreed, many libraries and frameworks have built in support and simpler syntax for computed values, like MobX, or even older frameworks Ractive or Knockout. React takes a very "code-y" approach to this, which I guess some people like.
- HeyImAlex 4y agoI’m in the process of converting a large knockout app to react and computed values are definitely what I miss most. They’re defined on the class (normal react practices prefer everything to be a plain object), they can reference other values/computeds internally just by calling this.computed (in react you have to manually chain the results through useMemo calls, and even with reselect there’s the added step of specifying all of your dependencies), they’re computed on demand and track their dependencies lazily (in react if you want a conditional useMemo you have to just early return null from the callback), and they’re conveniently useable in both model code and component code. I haven’t found a way to convert these that doesn’t feel like a complete regression in terms of code readability and ease of use.
- brundolf 4y agoThis talk suggests they're exploring ways to improve the DX: https://youtu.be/lGEMwh32soc https://youtu.be/lGEMwh32soc
- worble 4y agoWhile I personally like React, I have to say the design of the library is just so awful and non-intuitive. While I can maintain a legible codebase myself, as soon as juniors in my work are involved I have to spend a lot of time reviewing PR's, fixing changes and explaining concepts in order to make sure that the application actually runs correctly and isn't, say, infinite looping in a useEffect or something like that. I only rant about this here because I think useCallback is pretty awful design - separate functions that only exist as syntactic sugar are terrible for user readability. A lot of people probably know useMemo as it's quite easy to understand and used somewhat frequently, but if I were to use useCallback in my code it would probably cause a lot of others at my work to then have to go scouring the docs to figure what the heck this hook exactly does. On the other hand, just forcing users call useMemo and return a function means that everyone who knows useMemo knows what's happening. Unless I'm completely misunderstanding how useCallback works, perhaps React actually does some extra optimization under the hood or for this or something.
- michaelsalim 4y agoWhile I agree with with that useEffect can be non-intuitive and easy to misuse, I think useCallback is pretty nice to have. From what I'm aware, it's as you said. It's simply a syntactic sugar for useMemo if you want to memoize functions. Now if useCallback doesn't exist, you have to use useMemo and pass in a function to the function. Something like `useMemo(() => () => ...)`. Sure if you know what useMemo does then you'll know what it does. But I have a hard time believing that juniors would find that easier to read than useCallback(() => ...). All I need to say to them is: "Hey, if you want to memoize a function, use useCallback instead". And if I see useCallback used anywhere, I know for sure that it's memoizing a function. Rather than saying: "So you see that there's an extra bracket there? That means that you're returning a function. Yada yada" There's a grand total of 15 hooks[1], most of which you probably never ever have to use. I would expect all React developer to go through them all to see what they're about. I would also expect them to know & remember most of the basic ones: useState, useEffect, useContext, useReducer, useCallback, useMemo and useRef. That's a total of 7 functions. If they can't do that then I question the quality of today's developers. [1] https://reactjs.org/docs/hooks-reference.html https://reactjs.org/docs/hooks-reference.html
- babyshake 4y agoI completely understand why you would want to memoize values and reasons to use useMemo. But I don't really understand why you would want to memoize a function to avoid it being re-generated. I guess maybe it saves a tiny performance hit, but does useCallback result in significant performance improvements?
- edgyquant 4y agoIs this not extremely useful for hook interfaces?
- foob 4y agoIf you're passing the callback as a prop to a child component, then it will cause that component to be re-rendered every time the parent component renders unless you memoize the callback. This happens because React checks referential identity when determining whether props have changed. The performance hit of unnecessary re-renders can be fairly significant in large React apps.
- protonimitate 4y agoMemoizing the callback prop only matters if you wrap the child component in "React.memo". If you don't wrap the child component with "React.memo", every time the parent renders the child will render regardless of prop equality, even with memoized props/callbacks.
- fabian2k 4y agoReact will rerender the child component anyway in this case even with useCallback. Of course you can prevent this by using React.Memo on the child component, and in this case using useCallback makes it possible to optimize rerendering by providing stable values for functions you pass to that component. Adding useCallback for functions only does something useful if you also React.Memo those children. So while this is a very important optimization, it's not one you need to apply to everything.
- brundolf 4y agoIt actually doesn't directly help performance at all, because you're still creating a new function each time; they just get thrown away after the first time (until dependencies update) It only exists/is done to give you a stable reference so you can avoid triggering downstream dependencies (hook arrays and React.memo'd components)
- jefb 4y agoReact's push towards a functional model with all the use* hooks is so sad to watch. A stateless programming model in a domain where state is so fiercely coupled to program utility is inevitably going to spawn this garbage. Class based components with MobX managing state was, and still is, a dream to write __and__ read.
- jameshart 4y agoI wish people would stop saying this. Hooks aren’t functional or stateless. Literally, calling ‘useMemo’ twice returns two different objects, because the function keeps track in internal state of how many times it has been called. Hooks are very deeply imperative. They are a way of obtaining some benefits that are easily obtained in functional programming via higher-order functions, but expressed in a way that makes them easily consumed in an imperative code body.
- eurasiantiger 4y agoThat is all sorts of funny for people who remember PureComponent and all the hype about functional components. React has always been an exercise in smoke and mirrors.
- jefb 4y agoHooks are obviously not stateless - I'm saying they were an inevitable consequence of the push towards functional components and that they represent an inferior development experience. No one needed to write 2000 words on how to use setState.
- johnfn 4y agoCouldn't disagree more. Do you remember all the nonsense you had to read about componentWillUpdate, componentDidUpdate, getDerivedStateFromProps, componentWillMount, componentWillUnmount? What a mess. Hooks clean up so much of that complexity.
- bezier-curve 4y ago
- foomatic 4y agoSo useMemo === Vue's computed values??
- darepublic 4y agoWhy is Josh creating a useCallback with an empty array? Doesn't that result in a cache that gets invalidated every render (ie does nothing)?
- ntonozzi 4y agoNo, an empty array means that the cache is never invalidated.