Hacker News new | ask | show | jobs
by warent 2017 days ago
Is there anybody that develops on the frontend professionally fulltime and makes these kinds of complaints?

It seems like these are always drawn up by backend developers who lob fistfuls of aggression-poop over the fence for reasons beyond my fathoming, or junior developers (or UI folks who occasionally use javascript) that find it easier to trash on patterns rather than learn about them.

I have used React professionally for years and get the skepticism around hooks. It seemed really stupid to me before I learned about it. Why change what wasn't broken?

Now after learning about it I'll never go back to class components if it can be avoided and happily recommend hooks to all my clients who also end up loving them.

No idea what this promise chaining thing is that you're talking about. Sounds like a bad design pattern that has nothing to do with hooks. No idea why you're suggesting Redux has anything to do with hooks. They're completely different.

This meme is dead. Only a superficial understanding of React, or ingrained bad programming pattern habits, keep this meme alive.

4 comments

I've more or less driven frontend development with React at several companies over the last 4 years. While some of the complaints are exaggerated I don't think the overarching premise should be dismissed as "a meme."

> No idea what this promise chaining thing is that you're talking about.

If you have any asynchronous things going on in `useEffect`, you'll have to do something similar to that `await(0)` song and dance in tests. This specifically affects tests if you do things like update the UI by toggling loading spinners on await.

> Redux

s/Redux/higher order components. One of the motivations for hooks was that as a mechanism for logic composition, HOCs just felt awful to use. (So did render props, which everyone suddenly used for everything in a brief moment of collective insanity.)

> Only a superficial understanding of React

I think there's something in this. The fact is that good or bad, 1) hooks aren't intuitive, 2) hooks have basically doubled React's API surface area. Previously, React was so simple that a backend engineer could pick it up and get productive with it in half a week. That's much less the case these days. I've been onboarding devs to React for years, and these days there's a lot more "yeah, that's magic, you don't need to know how that works for now."

> If you have any asynchronous things going on in `useEffect`, you'll have to do something similar to that `await(0)` song and dance in tests. This specifically affects tests if you do things like update the UI by toggling loading spinners on await.

You should have a core (pure) functional component, that doesn't perform network requests, and an outer component for side effects.

Your testing for the inner component becomes trivial: Do the correct props product the correct HTML? Fairly trivial to validate. Use Enzyme, react-testing-library, etc.

The outer component, which contains side effects, can be covered through an end-to-end testing tool like Cypress.

> You should have a core (pure) functional component, that doesn't perform network requests, and an outer component for side effects

IMO, this is the biggest thing we lost with hooks. Before there were two different types of component, and you couldn't make a pure functional component stateful or effectful without completely rewriting it.

I love hooks, but I'm constantly asking in code reviews "are you sure this is where you want this state to live?".

The other big problem with hooks is that there are no safeguards (and little documentation) about using them wrong. The post you're responding to mentions using `useEffect` to toggle a loading spinner. This might make sense if the loading spinner is outside the React component tree, but if you're using useEffect to toggle some piece of React state, yer doin it wrong. Once you start slipping these kinds of hacks into a codebase, it's a slippery slope.

This is true as long as you're able to strictly enforce the container-presenter pattern, which is increasingly harder to do as an application grows in complexity.
If you're using a Design System (a base level of common UI components), the separation helps enforce the design system acting as the "presenter".

  You should have a core (pure) functional component, that doesn't perform network requests, and an outer component for side effects.
Except when you go to use that container component inside another component. Then you’re back to the same problem. Unless you’re advocating for a single container component at the top level in which case we completely agree!
> Previously, React was so simple that a backend engineer could pick it up and get productive with it in half a week.

With hooks, I've literally seen almost completely novice programmers (e.g., people who’d hacked out some powershell while working desktop support previously) pick up React and be productive in a month or so, while also learning JS and Python and SQL and backend development from scratch in parallel; if backend “engineers” can't do it in half a week or so, they’re hacks.

Yup, I use React professionally for four years now with some really big applications (10ks LOC) and I would always opt for class components.

The hooks API not only suffer from weird wording (how is useEffect more expressive than componentDidMount) but it introduced some concepts like dependency declarations (again useEffect) and a new meta syntax.

It could have been a good development if the published preview would have been a real request for comments with the possibility of changing something. But instead it was introduced as stable in basically the same form.

> how is useEffect more expressive than componentDidMount

Well, useEffect cross-cuts way more of the component lifecycle than just componentDidMount: it also handles componentDidUpdate and componentWillUnmount, and a few other things that didn't quite get lifecycle functions before. I suppose you could call it useWhenComponentMountsUpdatesOrWillUnmount, but "effect" as in "side effect" for when the component moves through lifecycle events isn't an uncommon name for that sort of thing (even outside of React).

  Is there anybody that develops on the frontend professionally fulltime and makes these kinds of complaints?
I do? These are all real problems I've encountered working on large apps at multiple organizations. React hooks are a constant source of difficult to write and non-deterministic tests. Class components also suffer from the same problems.

  Now after learning about it I'll never go back to class components.
Those aren't the only two options. What I'm advocating for is using react only for pure functional components without the use of any hooks. Hooks are completely isomorphic to class components. Instead of binding the `this` of class methods to an object as a class component would. React hooks maintain basically the same thing in the background and bind it to the values of the hooks, identifying them by call order in your component. Which is why you can't call them conditionally. They're way nicer than class lifecycle methods. Primarily because they organize code that's related together, rather than by when in the lifeCycle it is triggered.

IMO state and side effects belong outside of the render functions. Not mixed up inside them. This is exactly what redux, cycles.js, Elm, MVC, etc do.

  No idea what this promise chaining thing is that you're talking about.
You know that async await just chains promises together right? e.g.

  async () => {
    await foo();
    await bar();
  }

   () => foo().then(() => bar());
So any callback that makes multiple API calls will require multiple `await wait(0)` in tests to allow for the mocked API calls to resolve before the UI will be finished updating.

  No idea why you're suggesting Redux has anything to do with hooks. They're completely different.
If you can't see why Redux is related to hooks, I don't know what to say. They're both approaches to managing the impure parts of your UI. I suppose you could continue to insult my experience as a frontend engineer.
I agree, the main issue that I’ve had is just that its easy for (usually junior) devs to accidentally make infinite loops with interdependent state + effect hooks. But besides that I would never go back to class components.