7 ms·
I don’t get the whole trend of jamming state in functions. hooks use closures for state and if you call hooks in wrong order you get the wrong values back. In t
by nojvek 7y ago
I don’t get the whole trend of jamming state in functions. hooks use closures for state and if you call hooks in wrong order you get the wrong values back. In this instance, this.refresh is magical.
One hard lesson I’ve learnt after doing 15 years of frontend is to avoid too much magic. As you build more complex things, it should be easy to bring in new devs and they should be able to simulate the system in their heads without expecting too many surprises. Or being laser diligent that a silly mistake could blow things up.
That’s what I like about original react. It was super duper simple idea. Classes are meant to have state. The state object is called state. Render function returns a view of state.
While generators are cool, all of this could be simply achieved with existing paradigms. That’s why I prefer preact over react. It’s way smaller than react, less bloated and equally fast.
- TomMarius 7y agoWhile I tend to agree, IMHO your example is off - it is a "state" property because the class is newly instantiated each time a render is going on, and then the property is magically re-populated for you so you can still treat the class like a class, not because "classes are meant to have state" - you would use class properties directly as your state if that was the case. Hooks are exactly the same magic (the state property is populated the same way as the useState hook works), only accessed differently.
- Kkoala 7y ago> the class is newly instantiated each time a render is going on No, it's not? Where do you think the state goes, if the instance doesn't hold it?
- TomMarius 7y agoIt's stored internally in React. The instance of your component does not hold the state, just a reference to the state object which is repopulated each render (just like useState, it's the exact same mechanism), and after the render is done, the instance is destroyed. More here: https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html https://reactjs.org/blog/2015/12/18/react-components-element...
- zwily 7y agoThe instance of the class isn’t destroyed every render... you can keep other state on it too that is persisted between renders, changing it just won’t trigger a render.
- nightski 7y agoSure that is the way it works now. Is that a guarantee of React though or implicit behavior that could change in the future?
- boubiyeah 7y agoIt's just an implementation detail.
- deleted 7y ago[deleted]
- TomMarius 7y agoYou are right. I tried it here, for others: https://codesandbox.io/s/crazy-bush-cg2i0?file=/src/App.js https://codesandbox.io/s/crazy-bush-cg2i0?file=/src/App.js
- exdsq 7y agoI don’t know how this library or React work, but you could pass the state as an argument to itself - then what GP said makes sense.
- bikeshaving 7y agoI’m not sure how Crank is more “magical” than any other framework. All `this.refresh` does is make the current component execute again. For function components, this means the component gets executed again, and for generator components, this means the generator instance gets stepped through again. I think once you get the hang of generator functions and how yield work it might sort of click what Crank is doing under the hood.
- emteycz 7y agoIsn't the point that it's less magical - stuff goes where you expect it and does what you expect, not where the framework magically and by convention places it?
- orta 7y agoI believe bikeshaving's point above is that you learn the semantics of generator functions in JavaScript and that's your 'magic convention' - one that's not unique to this library because it comes form the languagee
- bikeshaving 7y agoIf the OP was saying that Crank is less magical then I agree. Although it always made me sad that we measure APIs based on how little magic they bring. Like go to Disney World or something.
- crubier 7y agoThe annoying thing with function purity fanaticism is that it is out of touch with reality. State. Exists. State exists, so let’s deal with it with the tools that the language provides, instead of pretending it does not exist, just to realize later that it does and jamming as hoc answers to this initial oversight. A UI component is fundamentally “something that generates values (view objects) asynchronously (over human-scale timeframes)”. That’s the definition of an async generator!
- josteink 7y ago> The annoying thing with function purity fanaticism is that it is out of touch with reality. State. Exists. It’s the opposite of all-state fanaticism, where nothing can be done or calculated without first 1. Creating classes, 2. Mutating their states, and often 3. Mutating global state. And then... magic! Both kinds of fanaticism are bad, and a middle-ground is probably best. Keep it simple. Use the best tool for the job, etc. That said, having worked with lots of code deeply inflected with global state, I’m more lenient to accept function-purity fanaticism over all-state fanaticism because at least then you only need to understand this one local oddity, not how it depends on the entirety of the rest of the codebase.
- crubier 7y agoI agree with that and I personally dislike OOP a lot and am much more on the FP side. But sometimes as you say a middle ground is best, especially when the thing is intrinsically stateful. But I have to say Dan Abramov does a good job of explaining why they need that purity here and it makes sense https://www.reddit.com/r/javascript/comments/g1zj87/crankjs_an_alternative_to_reactjs_with_built_in/fnkkgg3/?utm_source=share&utm_medium=ios_app&utm_name=iossmf https://www.reddit.com/r/javascript/comments/g1zj87/crankjs_...
- deleted 7y ago[deleted]
- exdsq 7y agoI think the state monad in F# makes a lot of sense - I'm now on the functional side after (finally) understanding it.
- namelosw 7y agoWhat if there’s no class in the language? The ‘original React’ as you mentioned for example, was modeled in standard ML. There’s no class in the language and it is okay to model the state in function.
- jameslk 7y agoWhy is this important? Especially in regards to the author's point about keeping frontend development simple?
- namelosw 7y agoBecause class is neither simple nor mandatory. And people have to do massive meaningless things like swapping between class and function components every day, because of the introduction and elimination of states.
- pier25 7y agoThere was OOP in JavaScript before classes existed via prototype.
- Kiro 7y ago> Classes are meant to have state. The state object is called state. Except that's not how React works at all. There's no state in the class that lives between renders, it only seems that way due to... magic. The class gets destroyed and created between each render and the state object is automagically recreated with the previous state. You can complain about Hooks but saying they are magical and React classes are not is just wrong.
- flowerlad 7y ago> hooks use closures for state and if you call hooks in wrong order you get the wrong values back. Calling hooks in wrong order gets the wrong value back? Can you explain this one?
- rossta 7y agoHooks rely on a persistent call index. Here are a few posts that explain in more detail: https://overreacted.io/why-do-hooks-rely-on-call-order/ https://overreacted.io/why-do-hooks-rely-on-call-order/ https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884 https://github.com/reactjs/rfcs/pull/68#issuecomment-4393148...
- TomMarius 7y agoBut why would you even change the order? I don't understand how can this be an issue if you treat it as a static declaration which it simulates.
- rssbnjmnfrncs 7y agoWhat if you wanted to return early in the component? E.g. a hook has returned a certain value and you now want to stop all other execution and return null. With hooks you can't as that would change the order.
- TomMarius 7y agoYeah but you also wouldn't try to return in the middle of function argument declarations. I know it's a little weird, but just treat it as a declaration block and you won't have any problems, what you're proposing is impossible with react architecture as a whole anyways (because the next component would get wrong state cells, it's a stack).
- draw_down 7y ago"Calling in the wrong order" is not an actual concern when writing React code. What you actually need to do is make sure that they aren't called conditionally. (For example, if your function checks some condition and then returns null, that must happen after any hooks are called.) This would be annoying if you had to do it yourself, but that's what linters are for. Ends up not being a big issue in practice.
- tchaffee 7y agoGenerators will likely be a new paradigm. They are too powerful for senior devs to ignore. And so the junior devs will be taught. Like promises were taught.
- akritrime 7y agoWait that doesn't make sense, was generators in the language before Promises, actually isn't await based on generators? How is that a new paradigm?
- tchaffee 7y agoPromises and generators were ES6, so around the same time. Although people were using promises long before it became an official feature in ES6. I remember using promises as far back as 2012 or earlier - jquery had them. ES6 was 2015. Await and async came after in ES7 and can be considered to use yield[1]. So there you go - that's a perfect example of the power of generators. Promises used to be more difficult until they were simplified using generators. [1] https://stackoverflow.com/questions/36196608/difference-between-async-await-and-es6-yield-with-generators https://stackoverflow.com/questions/36196608/difference-betw...
- ponyous 7y agoI prefer to avoid them. Debugging can be way harder. Remember good old days when you could understand minified JS relatively easily? Look at webpack bundle + babel with generators. Horror to work with. Yeah, I know sourcemaps and all that, but even sourcemaps workflow is impacted; setting breakpoints can be weird, debuggers are still not perfect.
- tchaffee 7y agoI think you are mixing up concerns. Webpack + babel does make debugging harder in general. Because you are looking at the output of a compiler. But what does that have to do with generators? Do you have a specific concern about how Babel "compiles" generator functions using switch? Again, I tend not to look at compiled code, but I think the babel output for a generator function is easy to read.