9 ms·
React's UseRef Deep Dive
- iansinnott 6y agoI'm a bit torn on the hooks feature since it seems like a great example of something that's easy but not simple [1], as well as going against React's prior principle of minimizing the API [2]. I'm glad the article also shows how to use the more traditional API as well, even if it is a bit more verbose. [1]: https://www.infoq.com/presentations/Simple-Made-Easy/ https://www.infoq.com/presentations/Simple-Made-Easy/ [2]: https://www.youtube.com/watch?v=4anAwXYqLG8 https://www.youtube.com/watch?v=4anAwXYqLG8
- bern4444 6y agoI disagree that hooks increase the API surface. They decrease the React API. Before hooks, if you wanted a stateful component you had to use class components with all of their specific methods (didMount, didUpdate, shouldUpdate, render etc). Hooks allow functional components to have state, and a functional component in and of itself has an even smaller API than the class. The React API vastly decreases. A single hook, useEffect, replaces at least 3 methods (didMount, didUpdate, willUnmount) that previously had to written out separately in class components. Each of those methods had to contain logic for ALL your state and side effects so they could very easily grow in scope and be responsible for handling many things. Now each individual concern can be packaged up in its own useEffect call. If I have state that is relevant to the useEffect call, than I just build my own custom hook that binds the stateful data with the useEffect. Because hooks are just functions built up from other hooks, I'm no longer constrained by the React API (its effectively gone) and I can so much more easily the abstractions I need that can be shared across components.
- chrisdalke 6y agoOne other common use for useRef that isn't mentioned here is to bridge your React component with a JS library outside the React ecosystem. For example, if you wanted to instantiate a charting library like uPlot (https://github.com/leeoniya/uPlot https://github.com/leeoniya/uPlot) you might instantiate a uPlot object storing state and methods for the chart. You can perform the chart initialization in a useEffect hook, and use a ref to keep a reference to the instance you've created.
- renke1 6y agoVery important use case. Actually, I am baffled how a lot of the common frameworks (React, Angular) omit some kind of documentation on how to integrate with third-party libraries that operate on the DOM directly (charting being a very good example) or how do something imperatively with the DOM (e.g. scroll to element after the user did something). In React I actually know how to do it properly, in Angular, however, I am completely lost how to do it.
- ldite 6y agoIsn't this documented here for react? https://reactjs.org/docs/integrating-with-other-libraries.html https://reactjs.org/docs/integrating-with-other-libraries.ht...
- renke1 6y agoIndeed, no hooks mentioned on that page, though. Also, on first glance, that looks like trivial integrations. Ah, I also forgot to mention, what I'd like to see is more documentation on how to hide an imperative API behind a more declarative React/Angular etc. API. That's not always trivial but often what you want. I think it's especially important because while you often can find ready-made wrapper for popular pure JS libraries they are usually abandoned (and thus don't keep up with the latest versions) or have some flaw that bites you sooner or later. My current recommendation is to write your own wrapper unless the wrapper is an official one of the authors of the underlying JS library. Naturally, that's not always feasible for complex libraries, but matter of fact you don't always need the full functionality of that library so you only have to wrap what you need.
- chrisdalke 6y agoI completely agree -- I've been bitten a few times using React wrappers that turn out to have subtle flaws or are unmaintained. Generally I just write my own wrapper with some clunky combination of hooks to manage the lifecycle of data. One common pattern I end up using for a lot of imperative calls is a "useAsyncFunction" hook which runs any async function, returns state for loading, error, and the result of that function. Unfortunately each library handles DOM manipulation, configuration options, callbacks, instantiation, etc. in its own way, and so I don't think there's any generalized solution.
- eyelidlessness 6y agoWell if I wasn’t already convinced that hooks were a bad idea, this cemented it for me. What a bunch of confusing complexity to mix up with something that otherwise looks like a function. Data in, data out, and mysterious side effects that look like functions too! Track them... with dev tools I guess? I’m sure they’re plenty testable... with mocks? I’ve spent a lot of time criticizing angular for implicit magic, but at least they’ve tried to make it seem like you can pass values and substitute things. I still vastly prefer JSX for frontend dev but I think really that’s about all I care for in this ecosystem.
- bern4444 6y agoHooks are the place to segment out effectful code from otherwise pure code useRef is a hook to serve just that purpose as is useState and useEffect. Building new hooks off of these base hooks lets you write your own custom hooks to handle whatever side effects you need. The existence of a hook is what should alert you to the fact that there may be some side effect thing happening here. Not sure if this applies to you but I've found that most people who criticize hooks haven't made the leap to using custom hooks and have instead only used ones provided to them (useState, useEffect, etc). Hooks are an incredible way of encapsulating behavior, separating out that behavior from a component, and exposing that behavior to any component that needs the same behavior. Check out this video for a practical example: https://www.youtube.com/watch?v=nUzLlHFVXx0 https://www.youtube.com/watch?v=nUzLlHFVXx0 I'm in the middle of a big refactor and writing reusable custom hooks are an absolute savior to share functionality across components that may have nothing to do with each other. Hooks are functions, which is why we can compose them to build new behavior from smaller ones. That's the point. Just cause a thing is a function doesn't mean its pure. Like I said above, hooks are often meant to contain the impure parts of your otherwise declartive and pure UI expressing the UI as a function of state.
- recursive 6y agoIf someone thought hooks were a bad idea, how and why would they ever "make the leap" to using them more than they have to?
- wokwokwok 6y ago> However, if you only reference inputRef inside useEffect then it'll always reference the DOM node so you don't need to worry about it being undefined. This isn't correct; it's well documented [1], but people seem to often think this is true; if you reference it in multiple places or not is irrelevant. Passing a ref in to the dependencies of `useEffect` doesn't work either. Mostly I like hooks, but this one in particular seems to trip people up a lot; I'd go as far as to say that using callback refs should be the only supported way of using them; the normal one is pretty much broken by default for any component that isn't entirely trivial. [1] - I think https://medium.com/@teh_builder/ref-objects-inside-useeffect-hooks-eb7c15198780 https://medium.com/@teh_builder/ref-objects-inside-useeffect... covers this pretty carefully.
- BigJono 6y agoThis isn't a "deep dive" in any sense of the word. Call it what it is: 'useRef tutorial'. If I'm opening up something called "deep dive" on a topic I don't know very well then I expect to learn at least something I don't already know from 5 minutes of reading the official docs. Also, why even bother giving an example of useCallback if all the example does is log something to the console? Especially immediately following a section called "Real world use cases". This is how newbs get the mistaken idea that you need shit like useCallback to show and hide an element based on state and you end up with overengineered code everywhere. Examples of library functionality should be of something that you should actually use that functionality for (because it's impossible or impractical to write in other ways). Not just because it makes the docs better, but because it gives you a chance to run into a big red flag when you've implemented something and realise you can't actually find a use case for it. Then again half the people writing docs for libraries in React land don't even use the libraries they're documenting.
- BreakfastB0b 6y agoHooks are the worst thing to ever happen to React. They're so easy to get started with but every codebase I've seen adopt them has turned into complete untestable spaghetti. Mixing stateful effectful code inside what would otherwise be a pure declarative render function leads to so much complexity in an attempt to bridge the two paradigms. Junior engineers are also constantly tripped up by the subtleties of `useEffect` and `useState`. Furthermore I think attempting to "encapsulate" side effects is a bad approach to writing testable programs. Most React components that use hooks end up having several chains of promises inside them but no way to await the final promise meaning tests have to be full of await wait(0) await wait(0) await wait(0) God forbid someone comes along and tries to be clever and replaces it with await wait(3) which now makes the test non-deterministic. Cycle.js is the only framework that seems to get this right by acknowledging that a component doesn't just output JSX, but actually outputs JSX, HTTP Requests, etc. Look, I get that Redux was a pain in the ass with all the boilerplate, but how did we throw the baby (unidirectional data flow) out with the bathwater. I no longer advertise that I know frontend development because the entire react community seems to have lost its mind.
- eitland 6y agoI haven't used React and React hooks as long as I have used Java and Maven, but consider this: If many successful people voluntarily use something you cannot understand there is always the possibility that you are the one who are missing out on something. (FWIW: I've been there myself)
- sbergot 6y agoI have used them on a medium project. I enjoy them very much but I have seen a lot of people struggle with the "rules of hooks"* I can see why some people prefer to use classes where the design is cleaner (even though you are more limited). *: https://reactjs.org/docs/hooks-rules.html#:~:text=Only%20Call%20Hooks%20at%20the%20Top%20Level&text=Instead%2C%20always%20use%20Hooks%20at,multiple%20useState%20and%20useEffect%20calls https://reactjs.org/docs/hooks-rules.html#:~:text=Only%20Cal....
- deleted 6y ago[deleted]
- timdaub 6y agoFor some reason I never ran into any problems with lifecycle methods of class components. I mean, for testing, having too many class methods is clearly annoying so I try encapsulate as much functionality into small and separate functions. But yeah, apart from that I never saw the need to use hooks. I mean either I write a functional component without state or I write a class component. That's it. I hope they don't deprecate lifecycle methods. Such a great interface!
- gherkinnn 6y agoNice presentation. More approachable than Reacts docs, so thanks.
- blumomo 6y agoThere's lot of ranting here against react hooks. Just came here to say that I use them with much pleasure, they help me building functional (view) components which map their internal state or external state (pulled in via custom hooks or 3rd party hooks such as useQuery() from Apollo GraphQL). And a view's side effects are made explicit with useEffect(). Awesome, love it.
- elramon 6y agowtf is wrong with yall hooks hater. i mean hooks are a pleasure to work with, surely better of the old class based implementation that is nothing but a class with some objects used as a components state. with all the previous lifecycle methods that causes unnecessary side effects. You said "What a bunch of confusing complexity...", dude if you dont get it it does not means that they are confusing. cm'on
- bern4444 6y agoTotally agree, I think most of the people hating on hooks haven't actually use them to write their own custom hooks or leverage their composable and reusable nature