News for hackers. Stuff that matters.
Re:Introducing Hooks by adriancooney on Thursday October 25, 2018 @04:58PM (#18304526)
My gut reaction is that Hooks isn't the greatest addition to React. One thing I've always pitched about React is the clean and extremely explicit API (with `dangerouslySetInnerHTML` being my favourite example). The hooks API is taking the dangerous road down to implicitness and magic which can only ever mean bad things in my book.

It's really not clear to me how calling the setter for these individual pieces of state triggers a render. It seems the `useState` call is implicitly linked to the calling component no matter how far down the call stack (with only a linting check keeping the safety on this footgun). I was also surprised to see the concept of reducers making their way to the API. We're being told the "classes are the biggest barrier to learning React" yet the notoriously difficult concept of reducers has its own method. Don't get me wrong, I _love_ Redux however I'm not sure I can get behind the shade for classes.

I'll have to play around with hooks before I can make a final call though because I have the utmost respect for everyone behind this project.

An interesting observation: I think this is the first piece of API that contains the word "assumes" [1].

[1] https://www.google.ie/search?q=site%3Areactjs.org%2Fdocs+%22...

Re:Introducing Hooks by acemarke on Thursday October 25, 2018 @05:42PM (#18304831)
Have you looked at what `React.Component.setState()` actually does under the hood? The logic isn't implemented in `React.Component` itself - instead, it tells the core React rendering logic to queue up a re-render. The real work is all inside React's internals.

I agree that the `useState()` aspect _looks_ a bit magical, but it's ultimately doing the same thing that `setState()` does in the end. React already knows what component this is, and you're telling it to queue up a re-render for that component.

Also interestingly, it seems that `useState()` is actually a wrapper around `useReducer()`, and not vice-versa :)

Re:Introducing Hooks by wereHamster on Thursday October 25, 2018 @06:16PM (#18305075)
The 'this' in 'this.setState()' tells react which component queued the setState. With the new API that information is collected by react through.. ehm.. some kind of magic.

I understand why the react developers chose not to make the component an explicit argument in the new API, as it would open doors to misuse. But magic never seems to work out in the long run, IME.

Re:Introducing Hooks by acemarke on Thursday October 25, 2018 @06:23PM (#18305117)
I'd agree it's "magic" in the sense that it's not entirely visible to the end user. But, the key is that React is _already_ tracking _which_ component it renders as it traverses through the component tree. It's just now also keeping track of some additional data as it goes through the process of rendering that component. So in that sense, it's not any more "magical" than any of the existing render algorithm.
Re:Introducing Hooks by badestrand on Friday October 26, 2018 @12:34AM (#18306801)
The problem is that the hooks seem to be much more restricting than setState. You can `if (condition) this.setState({x: 1})` but you can not with hooks because React keeps track and doesn't allow you to break out of a very narrow usage.

Look at the rules from the docs:

> Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.

> Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions.

I think this will lead to junior developers to not understand the React framework but to just accept "the way to do things" and do what the docs say, without ever questioning anything.

Re:Introducing Hooks by scq on Friday October 26, 2018 @01:06AM (#18306907)
I think those rules only apply to useState and useEffect themselves, and not to the setState function you get back when you call useState.
Re:Introducing Hooks by DougBTX on Friday October 26, 2018 @02:56AM (#18307283)
Yes, I think you’re right, there are different restrictions on when useState and setState, though it is worrying seeing confusion straight away about it.

I wonder about a case where there is an expandable panel in a UI, and when expanded it should fetch then display data from a web service. Easy enough to do with this API by splitting the content of the panel out into a second component, but it is going to be very tempting to wrap that useEffect fetch call in an `if (expanded)` condition.

On the other hand, there are lots of positives about this design too, the correctly written code does look very elegant and I can see it solving real problems.

Re:Introducing Hooks by trixn on Friday October 26, 2018 @07:30AM (#18308293)
As I understood it you should not opt-in to use state conditionally in your component but you can still conditionally set the state. That means you should not conditionally call `useState` but it is fine to conditionally call the `setState` returned by the `useState`. That is not different to how you would use state in a class based component where you also wouldn't attach a state `this.state = {...}` somewhere in the middle of its lifetime. The component has state from the beginning of its lifetime or it hasn't state at all. There is not such concept as "Now that you are expanded you will transform into a stateful component".
Re:Introducing Hooks by dceddia on Friday October 26, 2018 @10:38AM (#18309581)
I think the recommended pattern if you need a "conditional effect" would be to just move the `if (expanded)` inside the effect instead of wrapping it.
Re:Introducing Hooks by tree_of_item on Friday October 26, 2018 @08:39AM (#18308632)
What is worrying about that useState/setState example? The person just didn't read the page properly, it's not an indictment of the API. Maybe give it a month or two before the claims about confusion, this was just someone skimming the page and missing some details.
Re:Introducing Hooks by rimunroe on Friday October 26, 2018 @05:22PM (#18312802)
I think it's best to treat the various hooks the same as method definitions: you wouldn't conditionally define componentDidUpdate or componentWillUnmount in a class component. Instead, you would conditionally do something within those (always-present) functions. The same applies for these hooks.
Re:Introducing Hooks by christopherscot on Sunday October 28, 2018 @07:56AM (#18320244)
I had this thought as well. Ironic isn’t it, given that the main reason for hooks is that “classes are hard”.
Re:Introducing Hooks by rimunroe on Friday November 02, 2018 @01:15PM (#18364823)
I'm unsure what's ironic about it. Hooks feel significantly easier to me than classes in a bunch of dimensions.

Classes come with a whole lot of syntax & concepts like constructors, instance vs class properties, autobinding, that are otherwise not used at all in React. They present barriers to optimizing code with compilers, and property names don't get minified.

Hooks are Just Functions though. They don't even have to deal with the most confusing aspect of functions in JS: "this"/calling context. You could easily consume them in ES3 by just not using array destructures and function keywords and it would barely get less readable.

Contrast this with classes, where new devs are often pushed to learn experimental and often-changing syntax just to avoid the awkwardness of working with the current specification for classes in JS. The following isn't allowed per the spec or any stage 4 proposal, but it's all over intro tutorials so that people don't have to manually bind methods in the constructor.

  class Foo { handleClick = event => {...} })
Re:Introducing Hooks by Vinnl on Friday October 26, 2018 @02:56AM (#18307284)
> I'd agree it's "magic" in the sense that it's not entirely visible to the end user.

I didn't dive into hooks to completely yet to have a proper opinion on it, but the primary disadvantage of "magic" is that the end user can not deduce what's going on just by looking at the code. If magic is therefore "only" restricted to the end user, that's not much of a restriction...

Re:Introducing Hooks by engineeringwoke on Friday October 26, 2018 @05:32AM (#18307862)
There's already so much magic going on in React's code base. For Fiber, they put the stack in the heap so they could go around the JavaScript call stack and schedule work as they see fit

The real magic is in traversal APIs, like Context

Re:Introducing Hooks by Vinnl on Friday October 26, 2018 @05:36AM (#18307872)
Oh absolutely - by now I have read through the docs, and as I mentioned at [1] as well, I'm even expecting hooks to do away with more magic than it introduces.

That said, my main point was that "it's only magic for end users" is not really a valid excuse :)

[1] https://twitter.com/VincentTunru/status/1055747566393085952

Re:Introducing Hooks by engineeringwoke on Friday October 26, 2018 @08:53AM (#18308719)
Agreed, it's not really a valid excuse. Hopefully a scheduler re-write comes along soon to alleviate those concerns. I absolutely share them; I can't read any of that code anymore
Re:Introducing Hooks by baddox on Thursday October 25, 2018 @09:18PM (#18306030)
I’m guessing that React is keeping track of the current component instance that is executing when the hook is called, instead of JavaScript keeping track of what ‘this’ is bound to when ‘this.setState’ is called. One could say that both systems are “magic,” but it looks like the React team considers the behavior of ‘this’ in JavaScript to be a source of confusion for React developers.
Re:Introducing Hooks by acemarke on Friday October 26, 2018 @01:21AM (#18306957)
Yes, yes, and yes.

You can see the current implementation in [email protected] - see https://unpkg.com/[email protected]/cjs/react-dom.dev... for the actual code. Do a search for some of the effect names, like `useLayoutEffect()`, to see the implementation details.

React already knows which specific component it's rendering, regardless of whether it's a class component instance, or a specific function component. Looks like what it's ultimately doing is just tracking some additional metadata added to React's internal bookkeeping - search for instances of things like `workInProgressHook.memoizedState`.

And as someone who spends a large portion of my time answering questions from new React devs, I can confirm that the behavior of `this` in classes is an _endless_ source of confusion. Mitigating that is going to be a big improvement long-term.

Re:Introducing Hooks by mygo on Thursday October 25, 2018 @08:40PM (#18305876)
I’ve seen this discussion pop up before in other frameworks I have used as they evolved over time. Interestingly enough my favorite framework went from being very magic to being less magic and more explicit and verbose. I liked it better when it was more magic.

Guess I’m in the silent group who isn’t bothered by a bit of magic, and actually likes it. Sometimes I don’t care too much what’s going on under the hood so long as I understand what to expect to happen. If it’s a good framework, magic or not, the documentation will do a good job of detailing how to use such magical features.

Re:Introducing Hooks by skissane on Thursday October 25, 2018 @09:19PM (#18306032)
Magic is great when it works. The problem is when it doesn't do what you are expecting, it can be much harder to troubleshoot. (Did I do something wrong? Am I hitting a bug?)

Magic hides internal details, hence users are less familiar with them, hence they struggle more to diagnose when the magic fails to happen.

Re:Introducing Hooks by albertgao on Sunday November 04, 2018 @03:40AM (#18374899)
Don't want to be rude. But, the truth is, it is only a magic if you just can't figure out how they implement it...
Re:Introducing Hooks by Illniyar on Friday October 26, 2018 @07:56AM (#18308417)
The magic isn't what React.Component itself does, really it's the use of global variables (or close enough), because there is no other way in js to know inside useState what component called it.

The only way I can see this implemented is that when react calls your component function, it then keeps it a note of it in somekind of globally shared variable and then when useState is called it access that same shared variable to get the state.

It's also dependent on call order - that's a sure sign of magic work.

Re:Introducing Hooks by ascagnel_ on Friday October 26, 2018 @08:42AM (#18308649)
React has some knowledge of a given component through the use of `createElement` (or its JSX equivalents), so it's not even using global variables.

https://reactjs.org/docs/hooks-faq.html#how-does-react-assoc...

The "memory cells" the FAQ mentions sounds awfully like a map structure where React uses some internal identifier generated on first render to map any state handlers. The only "magic" bit is that it relies on the order of the `use` calls to be the same every time.

Re:Introducing Hooks by Illniyar on Friday October 26, 2018 @10:38AM (#18309578)
It is a globally shared variable.

Really either react notifies or registers the component to the module to exports useState, or more likely useState goes to some react internal api and retrieves the currently running component.

It's as much a global variable as the singleton pattern.

Re:Introducing Hooks by adriancooney on Monday October 29, 2018 @12:20PM (#18328707)
After pouring over this API for the last 3 days and keeping up with the RFC, I think I have reversed my position. I felt I couldn't leave this comment like this because it doesn't reflect my opinion anymore. I think hooks are amazing. If the React team can nail the API down, I think hooks will be revolution in how we work in React. I still feel like it will make the barrier for entry a little harder but as an experienced React dev, they're fantastic.
Re:Introducing Hooks by rectangletangle on Thursday October 25, 2018 @05:34PM (#18304771)
Agreed, the explicit nature of React is a really appealing aspect of the framework to me. Coming from Angular 1, React is remarkably "magic free," while offering a comparable level of functionality.
Re:Introducing Hooks by ajcodez on Thursday October 25, 2018 @11:21PM (#18306518)
Agreed it’s implicit. I think it works by keeping track of start and end of Component rendering and counting the function calls to useState in between. You can imagine the following sequence of events.

- Enter Component A

- Use State A0 (does not exist, set default value)

- Exit Component A

Where calling setA0 sets the value at index 0 for Component instance A and queues render again.

- Enter Component A

- Use State A0 (has existing value)

- Exit Component A

Re:Introducing Hooks by yaymo on Friday October 26, 2018 @09:15AM (#18308845)
i don't trust anyone who "loves redux"