Hacker News new | comments | ask | show | jobs | submit login
Making SetInterval Declarative with React Hooks (overreacted.io)
99 points by clessg 12 days ago | hide | past | web | favorite | 78 comments

Maybe I am crazy or old school but I though the concept of creating component as a class with standard functions to override (and defining a contract with props types) took a unwieldy language like JS and gave a sane and standard approach to it.

I now look at more "modern" functional components /w hooks and find it VERY hard to understand the data a component takes and how it uses/responses to interactions.

It feels like react was class based... and now that functional coding is the "in thing" its trying to shoehorn everything into functional components. In the end it really turns me off to functional programming as I see many developers sacrificing readable/understandable components to save a few lines of code.

Hooks address a very specific problem with classes: composability.

You can use the various builtin hooks to do stuff that (in class-based React) previously required implementing methods (eg. componentDidUpdate). Using those methods works fine until you want to split out and reuse part of those methods in other components.

You can certainly try class composition: creating little classes that you call in each of the relevant lifecycle methods. However this adds a lot of boilerplate to components which use the composed objects (as is common with class composition). It's also awkward to share the setState API with these composed classes.

The Custom Hooks approach[1] with React Hooks just makes it really easy to use state and lifecycle functionality when extracting common behaviour to can be shared between multiple components.

React has tried to address this composition issue several times in the past, and I think hooks are the nicest yet:

React's old 'Mixins' feature got a lot of the way there, but still didn't compose perfectly. For example, you had to avoid method and state key name collisions between mixins.

Creating a 'Higher Order Component' is another approach, which is less verbose than class composition, but makes your component tree deeper, and can also be annoying to statically type.

The community also came up with 'Render Props' to address much the same issue.

And of course, you can always just continue to use classes if you aren't experiencing any of these pain points.

Hooks just compose quite nicely in cases where none of these other approaches do.

[1]: https://reactjs.org/docs/hooks-custom.html

Is all this because inheritance is discouraged? Seems weird to got to that much trouble to avoid a builtin language feature that does the thing you want, which is reuse methods across components.

How do you compose two base classes into a subclass? That's basically what hooks allows. You can use two different, unrelated custom hooks in one component, and a different combination in another component, without having to bundle them into base classes.

> How do you compose two base classes into a subclass?

In most other OOP languages besides JS, the obvious answer would be to use traits.

Traits are okay: React 'Mixins' which I mentioned in my parent post are basically traits but at the framework level, which allows them to be smart about composing/merging the use of framework functionality normally accessed by overriding superclass methods (eg. componentDidUpdate). Traits still have the composability issues I mentioned for React Mixins: how do you avoid collisions between the namespaces of different traits while still allowing some to compose others?

Hence why I've been playing around with class decorators and friends to try and figure out a nice way to do method modifiers, traits, etc.

But I got sidetracked with "but howtf do I make typescript understand the resulting signatures" and then got nerd sniped by something else.

Hopefully eventually I'll get back to it.

If you want to understand what Hooks are for, I wrote this piece:


I hope you find it helpful!

Hooks aren't _quite_ like traits or mixins or anything else. You can apply the same Hook multiple times and pass values between them. That's what makes them powerful.

Look at my last demo.


Yeah, definitely a different beast. I've done things with what's basically dynamic scope trickery before now, though it didn't look exactly like hooks.

I still want traits because I've got very fond of doing class-with-read-only-members type stuff and being able to compose functionality together works really nicely in that regard

(nonetheless, I very much appreciate your efforts on elucidating hooks - I think most of the reason I'm replying this confidently is as combination of your articles and the reference docs :)

Maybe React hooks are a bit different, but Drupal was heavily hook based, and then starting going away from that in favor of Symfony components in recent years, which are class based and utilize inheritance. Also, UI has typically been considered one of the areas where OOP is well suited for, from Smalltalk to the Web DOM.

> UI has typically been considered one of the areas where OOP is well suited for

Without any evidence to support it. It's one of those phrases that gets repeated without critical thought.

Agreed. The "everything needs to be a react component" is bad IMO. My example, I'm making an image viewer. I want a context menu. IMO the ideal solution some generic right-click (context menu) function/handler. you attach it to each image. On right click the image is passed to the handler and the handler does something with it. That's relatively low overhead. There's no per image data.

But the React stuff I found made a context menu of nested components per image. Effectively <image><contextmenu><menuitem/><menuitem/><menuitem/><menuitem/><menuitem/></contextmenu></image>. For 1000 images that's 6 thousand components created, 6000 things added to the virtual dom to be diffed, 11000 considering the content of each menuitem is actually yet another dom node.

There's tons of react libraries like that where they try to shovel every concept into a component.

This just sounds like inexperienced programmers. I've played around with React and it doesn't seem like there is anything special about React that would prevent you from creating a single instance of a component and have it's state update based on what image you are right-clicking on.

In your example, the contextmenu component should not be created until the image is right-clicked.

So your <image> code would look something like this:

    return (<><img .../> {contextMenuActive ? <contextmenu>...</contextmenu> : null}</>);

> IMO the ideal solution some generic right-click (context menu) function/handler. you attach it to each image

Ideally, you would only have a single event listener that handles events for all images.

With React, it's one and the same thing. React has a single event listener at the top level, then creates synthetic events that it passes down the tree. You can still do native event listeners, but there's no reason to, except for listening for events on `window`, etc.

Look into portals https://reactjs.org/docs/portals.html. The menu should probably be owned by a shared component somewhere in the root of the tree, and then children can ask it to open via handlers propagated somehow (context, redux, whatever).

Same. React passed the, "this is obvious and it's clear where it fits into the real world" test for me years ago with class based components.

But these new features aren't passing that test at all. I struggle to grok what hooks do that I was missing before.

It gets me wondering if the React team is in a position to know when React is good enough and needs to be left alone for the most part.

The good news is that I seem to be able to just ignore hooks and remain very productive. I even started ignoring advice on when to use an SFC instead of a class and found myself happier and more productive with better code.

>I struggle to grok what hooks do that I was missing before.

I wrote about this too:


Hope it helps.

As another commenter note, the OP article discusses the pathological case. An API can make a hundred cases simpler but discussions will always focus on the few ones that got harder. The point of this post is to show how to work through this case and why the _end result_ is more flexible and powerful than before.

Thanks. Generally speaking my mindset is that the benefits will become clear in time, or they will be leveraged by others and invisible to my everyday use. But my final point still stands: the win with how React is evolving is that I can completely ignore these new features for a short/long/infinite amount of time and not be in trouble.

I have the same feeling. I would prefer to use classes rather than functions. More natural and nicely work with Typescript.

Luckily React is only a library and it is up to you how do you use it. I got used to working with classes and objects. For bigger and serious project I prefer Ember.js, which is modern and easy to pick up (https://yoember.com), but for some tiny project React is also a good choice with Typescript.

I guess hooks is a good option for devs who prefer functional programming.

Classes aren't really that great in React. You typically need do a lot of juggling to co-ordinate lifecycle hooks. Trying to do something like register, update and unregister a listener feels very verbose with classes because you don't truely control the instance lifecycle – React does.

Hooks work just fine in Typescript. Not just because Typescript already does will with Functional Programming, but because the types of most hook functions are generally rather simple.

`declare function useState<T>(startState: T): [T, (nextState: T) => void]` is pretty simple function signature and most cases Typescript picks up (infers) that T generic parameter for you based on startState. Almost every other Hook function has a similarly simple type signature, despite the complicated "guts" of how React keeps track of hooks internally. (Which also doesn't seem all that complicated, relatively speaking.)

(I still want a way to represent the order of effects / no effects in control flows rules in Typescript's type system, but linters will handle it fine. At this point it's mostly just a personal toy project/curiosity because Typescript feels like it has enough of the basic building blocks in the type system such as `never` to get quite close.)

React didn't even start out with classes — React.createClass came first. It allowed you to define lifecycle hooks for a component, but wasn't supposed to be a generic class implementation.

I'm in the same boat. While React IMO is miles better than any other JS view library, its component model is actually very constricting. It's a decent model that handles a wide array of developer skill levels and usage patterns, but it nevertheless gets in your way when you disagree with its opinions, such as the standard React data flow (state down, events up).

I was curios if a better solution is possible, and after a lot of research and trial and error I built a simple but efficient UI library that runs only on Observables – with no components and no virtual DOM. You get to use whatever tools your programming language affords you, be it classes or functional patterns or whatnot. The plot twist is that your programming language in this case is Scala.js, which is much richer in abstraction and composition methods than Javascript. Works great for me.

My library is https://github.com/raquo/Laminar, and I wrote a bit more on virtual DOM vs Observables here: https://github.com/raquo/Laminar/blob/master/docs/Virtual-DO...

There is some difficulty in understanding how this works at first if you haven't hit these problems before. But once you do, the payoff is immense.

You think of problems in terms of describing how data changes over time rather than how am I going to make this display. The JSX part of the code becomes an afterthought. In the same way you aren't thinking about what DOM mutations React is actually doing behind the scenes, don't worry too much about how it wires together just describe what it does. Counter is a wonderful example. Look how contained and directed the hooks version is compared to jumbled mess the class version is. Picture that class component was anymore complicated, tracing through these lifecycle methods to figure out what is happening under any number of different input changes. Where the hook tells you in its definition when it updates. Each new behavior is just listed after and self-contained. Consider how refactoring and breaking apart components works in both scenarios.

This paradigm is not new. New to React but not at all new to Frontend JS UI libraries. Ironically when presented in MobX, and KnockoutJS(way back in 2009) it was considered simple. Somehow in 2019 with how far we have progressed, it's too difficult?

Calling the class component a "jumbled mess" is nothing short of hyperbole. It could be simplified quite a bit however. The problem is an inappropriate use of "setInterval" here. If the author used a recursive "setTimeout" function instead, the entire "componentDidUpdate" function can be deleted. Alternatively, keep the setInterval and all the logic in componentDidUpdate could just be moved to the tick function.

This contrived example hasn't sold me on hooks at all.

I kinda feel like this might be a lot simpler if you could use it mobx style, i.e.

    useEffect(state => {
      // reading state.count registers a dependency on the count
but much though I've been enjoying mobx for model-ish things w/react I wonder if that would end up being too much spooky-action-at-a-distance

Wow, I really don't know what to think of this article. I have to give Dan credit that every time I thought the code started looking really crazy, he'd say something like: "Admittedly, [this] code can be disorienting. It’s mind-bending to mix opposite paradigms." And I think it's a good sign he recognizes the fair objections people will bring up.

In addition to the paradigm-mixing the article illustrates, I wonder if the actual hook APIs make things more confusing than necessary at some points. For example, in the `useEffect` hook API:

* the first argument is a function that on every render

* the return value of the first argument is a "cleanup" function which runs when the component is unmounted or before the effect is run again

* the third argument is an array of parameters which controls when the effect is run. If passed an empty array, the effect is only run at mount and cleaned up at unmount.

All the above means that the API is very implicit and doesn't self-document its intent all that well. An example, from the article:

  useEffect(() => {
    function tick() {

    let id = setInterval(tick, 1000);
    return () => clearInterval(id);
  }, []);
I'm sure with more use these hook patterns will become more familiar. But it's clearly a lot harder to learn and understand than the original simplicity that helped propel React to popularity.

Dan's arguments that hooks provide for easier abstraction and more composability is interesting to me though - if hooks are going to be "worth it" in the long run, I suspect this is why.

The pattern of returning an unregister function is a common one. But I agree that the cache key array is strange.

I'd almost suggest that a seperate useEffectOnce function would be better, but I'm sure the abstraction was heavily tested and bikeshedded before it was released in this form.

You could create userEffectOnce as a custom hook:

function useEffectOnce(callback) { useEffect(() => { return callback() }, []) }

I do React at work and Elm for personal projects, and I feel the React ecosystem is trying too hard to become something its not. Hooks to me are an added level of complexity, and doesn't simplify the way I write or test components. I don't really mind the class based components as I feel there is less magic.

Personally, React had a great run, but it's time to move on to a more purpose built language/framework.

I read half the article and got lost. What I like about the "original" React is that it is simple to understand, close to JavaScript in a sense that you do not need to learn that much and be able to have a good result. I'm reading more and more about Hooks and still have a hard time to have a clear idea of how to avoid these pitfalls. At the point I am, it seems that Hooks has a lot of hype from few big influencers but that the day-to-day developers will be lost.

Instead of spending hours reading, start playing with them, it is fun and in few hours you will get why people are excited for hooks!

Dan Abramov claims that React hooks haven't jumped the shark. All I'm seeing in this article is exactly that.

I’ve now converted a good chunk of a large stack over to them and the best way to describe them is this: they are as big an improvement to React as React was to its predecessors.

This example is meant to be a pathological case. The fact that you can build complex interface logic and bundle it into a function that can then be extended and composed is a huge leap forward.

I do think Hooks will take time for some of the best ones to become standard. While I see some early “lodash for hooks” like libararies appearing, I could also see a really nice PWA that let you search gists for popular hooks or similar.

Hooks are a very nice solution to a very hard problem. But unless you’ve done large scale frontend work and especially more complex interactive components it may be hard to see. Although just getting rid of all the decorators/HOCs is already a big win.

Agreed, we're using hooks over redux on a largish codebase and once you wrap your head around the model the only real frustration is not being able to use them in class components.

By "over redux" do you mean "with redux" or "instead of redux"? I haven't used hooks yet but if you are using hooks instead of redux, it confuses me on how hooks work. To me they seems to be replacing the need for a class with local state, not replacing a redux architecture?

I'm interested to hear more please :)

Sorry should have been clearer. It's more of a combination of react hooks and react context, hooks to deal with local state and context to provide reducer functionality for global state.

Just means you can have functional components that respond purely to effects from state changes locally or at global level

From my experience I found this kind of separation to be somewhat redundant and am simply using redux to manage all state — both global and local context.

This also means that components are simply components, and setTimeouts and everything else is moved out to redux thunk actions. Which makes hooks totally unneeded in my case.

I'll point out that we absolutely plan to ship hooks as part of the React-Redux library, but we need to do some internal reworking first to make that feasible. See this roadmap issue I just posted for details:


> am simply using redux to manage all state

This only works in small apps. I work on a medium sized app at work and we started that way too. It becomes a huge, sloppy mess in short order. Putting everything in Redux is akin to a desktop application that uses nothing but global state. Hooks are great because it keeps the state local, but it can be re-used across components if we need to.

I would disagree with you and say that from my own experience (not saying your experience is wrong obviously) it's quite the opposite; in small applications, using local states is fine, but as soon as your application grows, having everything inside a central store makes everything cleaner and much simpler, as multiple independent components might want to share state or listen to shared events, etc.

> as multiple independent components might want to share state or listen to shared events, etc.

If you recall, I said...

> Hooks are great because it keeps the state local, but it can be re-used across components if we need to.

The use case you just defined is exactly why hooks were created.

Are you implying the use of context when you say that hooks allow you to re-use state between components?

Legit question because I don't know hooks very well. To my understanding, hooks are just syntactic sugar to use and update local state in a function component. How does that help you share state between components?

I think he must be implying the use of Context as well.

That's where the real power is. Combining the 2. The pattern of use is DI even with a global store like Redux, making it not necessarily truly global. What Context does at a base is potentially use React Components as widely accessed stores. The simplest example usually involves abstracting a Parent Component's state/setState into state, and action functions wrapping a Context Provider.

To what degrees the stores should be laid out hierarchically mimicking the render tree is debatable. But often there is clear hierarchical ownership on large portions of the data. And often the question is what needs to be topmost and what belongs only within nested context. I think the opinion is still out on that. As you have suggested you could manage everything topmost.

Hooks make this really interesting in that they expose this idea of simple change management primitives to any Function component. So while it is still the Context API that allows the data to be shared, Hooks allow for re-usable patterns that can be used out of the box or compositionally built upon. So the Component that contains the provider has the ability through Hooks to do a really good impersonation of Redux(useReducer) or even MobX(useState + useMemo + useEffect). Does this replace those libraries? Probably not. But it is interesting how it gives a built in solution to choose to scale these solution with how you see fit. You have these tools at your disposal without much investment.

I do not imply the use of Context. useState() hooks into the local state of whatever component runs it. For example, if you have the following hook:

    function useMagicNumber(default) {
      const [magicNumber, setMagicNumber] = useState(default)

      return [magicNumber, setMagicNumber]
And the following two components that use said hook:

    function ExampleA({}) => {
      const [magicNumber, setMagicNumber] = useMagicNumber(1)
      console.log(magicNumber) // 1

    function ExampleB({}) => {
      const [magicNumber, setMagicNumber] = useMagicNumber(2)
      console.log(magicNumber) // 2
ExampleA and ExampleB share the same code that's run in the hook useMagicNumber, but the state reflected is unique to the component.

You're unnecessarily coupling your components to redux..

The only things that are "coupled" to redux are actions dispatched from components. They themselves are very abstract, and when needed are connected using { connect }.

> The fact that you can build complex interface logic and bundle it into a function that can then be extended and composed is a huge leap forward.

Unless you already used HOCs (in the Recompose sense).

Every single blog post is obsessed with comparing hooks with classes (I guess because it's the only thing they improve upon). What about HOCs? I'm not sure hooks are really that much of a leap forward compared to them.

HOCs only wart is their pollution of props which admittedly hooks solve (by virtue of using local variables), but hooks have their own warts too as evidenced in this article.

Hocs had several problems, they couldn't access context, re-using one result in another is hard, they create a new component for every thing you want to do, etc.

Take this example for instance: https://codesandbox.io/embed/26mjowzpr

It measures out the view, reads out media queries, uses the results to construct a grid, uses a hook to turn it into an animatable, and just spits out the view as if nothing happened. All of this in the same component, with small, re-usable utility functions tapping into the host-components lifecycles. Just by looking at it you know what it's doing.

This is how a component should behave from now on, an entity that hooks into the host, instead of a class the host calls into. In my experience this is the first time you can express logic linearly: x > y > z > view, without wraps, inversion of control and DI.

Now imagine doing this with hocs ... even stacking two is already destroying any hope of guessing what's going on.

As someone who uses Typescript, HOCs are a nightmare, and hooks are a world of difference.

Perhaps I'm just a bit dumb here, but a few of these comments confused me.

> However, this is a common source of mistakes if you’re not very familiar with JavaScript closures.

> The problem is that useEffect captures the count from the first render. It is equal to 0. We never re-apply the effect so the closure in setInterval always references the count from the first render, and count + 1 is always 1. Oops!

Perhaps I'm not understanding the second comment fully... This behavior is completely counter to how Javascript closures work in my mental model. I'm trying to figure out how a state hook differs in execution from a normal variable in module scope.

How does it differ from this [1] example.

[1] https://jsfiddle.net/xuz09cow/1/

The difference is that closedVariable would be created inside intervalFn (the component). In addition, the intervalFn may run many times, but the interval will only be set up once. This example illustrates the problem: https://jsfiddle.net/ov2msa4e/

Your code avoids the closure problem, but closedVariable would be more like a static variable — it'd be shared by every instance of the hook. Probably not what you intended!

Thank you for the example, Jake! It was very helpful. You and Jason's answer cleared it up for me.

The difference is subtle (and took me a bit to figure out!). In the article's example component, the component's "main" function gets re-run on every render and a new `count` variable is created each time. The effect function is only run once at the very first render, and only captures the value from this first render.

I'm having a little trouble explaining the difference well, I think this jsfiddle illustrates the incorrect case the article is talking about representatively: https://jsfiddle.net/7fLnvz5c/

Thanks Jason, this was very helpful for me. I think I was having trouble making the mental jump from reading the code as a normal function with state vs how a component instance is called and handled by React at runtime--your example helped me make that hurdle.

> Our “impedance mismatch” is not between Databases and Objects. It is between the React programming model and the imperative setInterval API.

I haven't used it much, but React gives me the feeling that it's trying to come up with hacks to shoehorn imperative UI (which seemingly can't go away) into the "the state is the UI" model. Anything with timers, or animations, or other things that reach across multiple renders seems to be poke through the nice React model because it by definition requires dropping the abstraction of the UI being defined by the state because the change is more "incremental" than transitioning to a new value.

(As an aside, I love the dark mode support on your website!)

> React gives me the feeling that it's trying to come up with hacks to shoehorn imperative UI

React IS a hack to shoehorn declarative UI into an imperative language and DOM system. All further progress in the field is going to be a collection of hacks.

ReasonML, Elm etc are clear ways forward that attempt to start from a clean slate, but you're trying to do declarative UI on JS+DOM, everything is going to be a hack. React is just the nicest currently available hack.

By this logic, though, everything declarative is a hack. Computers are imperative. At some point everything becomes an instruction; dig deep enough and all declarative code calls imperative code.

Pet peeve: using `let` when you could use `const`. I've been conditioned to read `let` as a statement of intent to mutate that variable and it irks me when they then... don't.

The funny thing is that with reactivity like Vue/MobX you don't actually _need_ to make setInterval (or any other function) declarative - the change detection system abstracts all this from you and you have one less concern to care about everywhere rather than having to do this manually in terms of hooks for every component.

Everything is just JavaScript (well... TypeScript) and the abstraction is solid enough none of this is a concern you have to deal with.

(I enjoyed reading the article - the writing was solid :))

That's true. In one sense perhaps hooks are trying to hard to model a different paradigm to what react runs on. But its interesting to see this approach as it applies this pattern to other change detection mechanisms not typically associated with fine grained change detection. Ive seen libraries apply hooks to like LitHTML in webcomponents. Its the first time Ive seen the potential for a universal API here. How sweet would it be if library writers could target hooks instead of a specific framework?

Can you share an example? I'm not familiar with how you'd define a component-specific interval.

Perhaps someone that knows more about hooks can help me to understand the trade-offs.

After looking at the intro: https://reactjs.org/docs/hooks-overview.html

My understanding is that each time that you call useState the renderer is keeping track of a state associated with the currently rendered component.

It’s a clever solution, but that implicit context bothers me a little bit. For comparison, Flutter makes the state relationship explicit: https://docs.flutter.io/flutter/widgets/StatefulWidget-class...

The Flutter approach is more verbose, and I don’t know if I like it or not. But the useState looks like a maintenance nightmare. There is no way to type that function usage correctly, and the dependency is not explicit (making refactoring and testing cumbersome).

Any experiences to share?

My eyes glazed over at this. I can follow the first code example with the explicit mount and unmount, but really not any of the others. I will pray I don't have to debug any website using these hooks features any time soon. This "declarative hook" ivory tower is for people with far much more time on their hands than I, I feel.

I've seen the sentiment expressed before and I think it will only get worse in the future. React now is very popular with smaller/medium companies, large enterprises like banks will surely jump to it after some delay. It's usually when the main talent moves off to something more exciting (what happened with rails -> node for example).

Even now it's hard to find someone good at idiomatic React, imagine the same situation when it's perhaps not as popular as it once was and internal projects are mature.

Codebases using declarative style are very hard for majority of programmers to grok in my experience, mostly because it's such a big paradigm shift and requires truly abstract thinking, also not generally something you learn at CS programs. It will either all be a big mess or require some senior high salaried people do the maintenance. That will be a good time to do frontend contracting for the enterprises and it's coming soon.

I find declarative style hard because you can’t use a debugger, which means you can’t “go in and look around”. You need to have a theory of what’s happening a priori that you can test. That means you need to model the internals of the tools in your mind to be able to make guesses. That means a slow learning curve.

That’s fine if it’s one of one or two major libraries that you use all the time every day. But in practice most of us are using dozens and dozens of tools, tools which change all the time, and we have to learn as we go. So these “big learning up front” APIs are just not very ergonomic for teams to engage.

Unless you’re Rails or React or something where you can claim to be basically a programming language or “standard library” in your own right, something everyone on a team will have already dedicated themselves to studying in depth.

My issue with hooks is the learning curve for novices. Previously, it was always easy to have answers to "how does this work?" questions.

Now, hooks give a lot of powerful ui l magic which lets programmers be super productive from day one, but we have a need for articles like this to describe things. It is not trivial anymore. A bit like rails-vs-sinatra story. React arrived to the magical stage and we already had ember for that. React was nice because there was no important magic.

Ah… who cares? I still gonna use it. It just means I will have to hire more senior devs instead of juniors.

Your experience might be different but I’ve seen many beginners who struggled with classes pick up Hooks very quickly. A lot of the confusion has to do with unlearning a different mental model. Experienced programmers tend to get more confused by Hooks than beginners.

Yes, there are pathological cases like this one. Somebody will put this useInterval on npm and then it won’t be a problem. I’m not convinced it be a big issue for beginners in practice based on my experience showing it to people and seeing them play with it.

Resetting the interval when the delay changes is probably not what you want either -- quickly changing the delay (even a little bit) won't give the timer a chance to fire. It would be better to compute a deadline internally, then move the deadline forward or backward according to how much the delay changed since the last call.

Good thing something like useInterval() can abstract these implementation details away so it can be made more precise with time. :-)

A setInterval/setTimeout can only be cleared (clearInterval/clearTimeout). Modifications have to pushed through clear -> set.

I found this talk from React Day Berlin quite helpful for understanding React hooks: https://www.youtube.com/watch?v=p8v9X2TNQKA (An Exploration of Reacts Exciting New Features - Ken Wheeler)

I'll repeat what I've mentioned several times with things like this, which is that to me hooks just feel like a more convoluted reinvention of mixins.

Hooks are composable, mixins are not.

Seems to me that deps are to (some) hooks as props are to components?

That's ... really not a bad first order approximation at all, and I'm going to steal it when trying to explain things to people. Thanks!

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact