6 ms·
I wanted to like React so bad. I tried. I loved JSX and really appreciated the way you could reuse components. That was all very cool, and I was initially quite
by ExtremisAndy 3y ago
I wanted to like React so bad. I tried. I loved JSX and really appreciated the way you could reuse components. That was all very cool, and I was initially quite enthusiastic about it. But for whatever reason, I just could not figure out state management/hooks. Drove me crazy. It just always felt so unnecessarily complicated compared to other languages and frameworks I've used (even vanilla JS). Now, don't get me wrong: I fully accept the blame here. I am mostly self-taught (and not even the best 'student' in that context, haha) so I'm sure I just lack the overall knowledge base/big-picture understanding to really appreciate what they've done here. I hope I'll give it another shot one day, and perhaps with fresh eyes (and maybe with the help of a patient tutor), it will all 'click'!
- fendy3002 3y agoHooks are complicated, but state/props is just right. Both enables you to enforce boundary and make contained components. If props and state are mixed / diluted, the component won't know when to do re-render and there'll be too many things to track, and there'll be many classic issues such as cyclic dependency and sluggish performance of two-way data binding. Hopefully you'll click on it someday
- deleted 3y ago[deleted]
- qudat 3y agoview = func(state). That’s the magic of react. The problem is no longer manually managing transitions between state but state itself. That’s why state management is so critical in the react ecosystem. Further, react has delegated two key features to userland: side effect and state management. Personally, I don’t want react to solve either of these problems because it’ll just turn into the disaster that is react server components: feature development driven by corporate interests (eg vercel).
- june_twenty 3y agoI think that view = func(state) is an unnecessary complicated way to describe frontend development.
- qudat 3y agoAfter years of react dev that is probably one of the wildest takes I’ve ever read. Kudos!
- june_twenty 3y agoHardly a wild take though, is it? You're in the context of "I am mostly self-taught (and not even the best 'student' in that context, haha) so I'm sure I just lack the overall knowledge base/big-picture understanding" and you come in and say view = func(state). Here's how the React docs introduce it: "React is a JavaScript library for rendering user interfaces (UI). UI is built from small units like buttons, text, and images. React lets you combine them into reusable, nestable components." Hopefully you can appreciate the difference.
- recursive 3y ago> view = func(state). If this was actually how it worked, I'd have much less problem with react. What I mean, specifically, is that not all function dependencies are explicit. This makes it look like the state is passed into some function. And then the view is returned, depending only on state. In reality, half the state is passed in (as in the argument to a function call), and half comes out of some mysterious hook storage structure. If the state was really a function argument, you could easily inspect the whole state in a debugger. Instead of... I'm not sure how you'd actually do that.
- laurencerowe 3y agoReact Developer Tools makes it easy to inspect component state in your browser. https://react.dev/learn/react-developer-tools https://react.dev/learn/react-developer-tools
- jbritton 3y agoThis brings up other questions too. Is the state on the client? How does one reconcile the server state and the client state. Is the client state a subset of server state? Is the client state a tree matching the view tree? Does the state contain only the UI data to be rendered or is it all app state.
- switz 3y ago> it’ll just turn into the disaster that is react server components: feature development driven by corporate interests (eg vercel) if you've followed along with the react team's discussions on server components, it is very clear that vercel implemented the react team's vision and less so the other way around. as someone who has been using them extensively, I understand why. they're delightful. vercel does control next.js which is the only framework to completely implement RSC, but as other frameworks catch up, RSC will have a wider surface area.
- yamtaddle 3y agoHooks are half of an object/class system (implemented on top of a language that already had a whole one—arguably, two, from a DX perspective, though they're one under-the-hood) with non-standard and hard-to-read declaration syntax and bizarre behavior (FIFO-by-declaration-order property access and method invocation). It's not your fault you're having trouble with them, they're a weird boondoggle.
- skydhash 3y agoHooks use a different paradigm, which is a solution to a problem you encounter when doing functional programming, which is persistence and side effects. The whole of React is to build a tree of objects that will be rendered into a HTML page. The previous class-based architecture made it easy to store state and add side effects to this tree, by using properties and methods. But pure functional programming makes these awkward as functions are transient, only transforming parameters into return values. I don't know exactly how – never had the time to properly research it – but, my current guess is that the hooks code taps into the scheduler/dispatcher – which handles the execution of the function representing the component – and stores value and logic somewhere. It uses the order of these calls as keys – you don't have to specify them – and provides the stored values as return values of the call of the hooks functions. Hooks are escape hatches from the functional paradigm of React's components. You are always providing new values, and it decides when to store the updated version – mostly based on the deps array. You then get back what you stored. On the surface, it's still basically functional, but the actual logic is not. It's more like a repository of code and values.
- super256 3y agoI find the hooks so much easier to use than e.g. Google's ViewModel solution in Jetpack. They are just a joy to use.
- WorldMaker 3y agoOne view of Hooks is that they are monadic or at least Monad-like and the deps arrays are a crude (reversed) notation for algebraic side effects. ("Reversed" because they declare which dependencies have side effects more than they declare which side effects the hooks themselves produce.) It's still so very functional programming-inspired, even if the execution engine (scheduler/dispatcher) isn't that much like the Monad runtimes of most functional programming languages and the various Hook "monads" don't get captured in even the return type of functions (much less the parameter types) and get elided away. (It could be more "traditionally JS monadic" if it [ab]used async/await syntax and needed some fancy return type, even though the concepts for hooks don't involve Promises [or Futures, being the slightly more common FP Monad name]. Though also, from Typescript patch notes, I've heard React is exploring [ab]using Promises for something like that in the near-ish future.) Monadic bindings needing to be in-order, just the like "Hook rules", isn't even that strange from an FP perspective: there can be a big difference in which of two Promises is awaited first. There can be a big difference in which IO binding executes first (you don't want to input something before the prompt of what to input is printed).
- tomcar288 3y agoDon't blame yourself. Software engineering tools are supposed to serve the programmer, not the other way around. If a tool is too hard to use, then you're using the wrong tool. Tools should serve the developer. I would recommend plain old javascript with a light wrapper on top, like jquery. I know i'll get downvoted for this but a lot of "modern" javascript frameworks don't properly abstract the underlying layer properly (read Joel spolsky's article on leaky abstractions) and this results in a lot of problems. Furthermore, they optimize for the wrong thing: writing code. Most engineers spend 95% of their day reading code and that's a lot harder than writing code.
- paulddraper 3y agoWith all due respect, this sounds like a "old dog"/"new tricks" scenario. "What's this .map() nonsense? The indexed for-loop always made sense to me."
- ern 3y agoThere are certainly benefits from doing things in new ways, but a lot of the time things swing too far in the opposite direction, and become of a form of “IQ signalling” for smart developers. It isn’t only front-end developers who are prone to this: 20 years ago, before FP became a mainstream thing, being able to do pointer arithmetic was seen as the differentiator between a “smart programmer” and a “bad programmer” (https://www.joelonsoftware.com/2006/10/25/the-guerrilla-guide-to-interviewing-version-30/ https://www.joelonsoftware.com/2006/10/25/the-guerrilla-guid...). Was React great and fun to work with? Yes, but then Redux came along and made something simple into something stilted. Our team used Mobx instead, which was simpler IIRC. Similarly it’s been a couple of years, but I remember React Hooks being a bit complicated for the value we got out of them. Ultimately, it’s hard to tell if something is an improvement, or a time suck to allow the elites to stand out. I stopped playing the game and stepped away from front-end development, as have many of my experienced colleagues. I’m assuming things have settled as Big Tech focusses on profitability rather than funding an endless parade of frameworks, and the IQ-signalling will become less prevalent as generative AI competes with the brainiacs. When that happens, I’ll dip my toes back in the world of front-end development.
- paulddraper 3y agoHooks are IMO one of the greatest innovations in UI programming. I'll draw an analogy. --- Why did async/await replace callbacks? They are really the same thing, aren't they? Aren't callbacks good enough? Async/await allowed programmers to write asynchronous code as if it were synchronous. --- Why did hooks replace classes/imperative? They are really the same thing, aren't they? Aren't classes/imperative good enough? Hooks allowed programmers to write stateful code as if it were stateless. function MyComponent() { const [value, setValue] = useState(false); const buttonClass = value ? "on" : "off"; return ( <button className={buttonClass} onClick={() => setValue(!value)} > {String(value)} </button> ); } This is functional code, without scary, hard-to-reason side-effects. Except for one limited part, which operates in a stateful way. I argue that this is simpler than the equivalent imperative-DOM modification code, and the gap between these only increases with real programs. This isn't just a weird "web bro" thing; the hooks paradigm is useful (in theory and practice) to every UI platform. I even wrote an implementation (closed source) for hooks in Angular. It was lovely.
- bernawil 3y agowhat do you mean async/await "replaced callbacks"? Async/await "replaced" Promises, specifically then/catch chaining. Turns out Promises can be syntactically-sugared to imperative try/catch blocks.
- paulddraper 3y agoAh but if I said "async/await replaced Promises", a pedantic HN poster would correct me :/ "No it didn't replace them"
- eyelidlessness 3y agoI’ll be more pedantic than that! Await is more akin to yield, the fact that it’s specific to promise resolution is a specialization of the more general function body suspension used by generators, with an extra specialization for event loop scheduling. And async just means you’re returning a promise no matter how your function exits.
- preommr 3y ago1) React has no state management - approach it not from what it should be, but what it is - a tree of components that just render their props and where each component has some internal state. 2) Components have behavior. In Class based components they were implemented as methods. Simple enough, classes have methods. If you think about an iteration of rendering the ui tree, it goes down the tree and calls the mount method for each component in the ui. With hooks, instead of calling a method on an instance, it's implemented as an inner function of a component that is also a function instead of a class. Instead of explicitly calling the mount method on a class instance, calling a function that's a component automatically runs it's inner mount method. The way that it knows the which inner function is a lifecycle hook is because you import something like 'useEffect' from the react library. And that global useEffect function knows the current component because the renderer sets it as it's going down the ui tree. Hooks are better because they can be written as arrow functions (more concise, cleaner), and because you're calling a framework function, that function can have more complex behavior like how useEffect can track when to update because it's being passed in an instance of something like an internal state variable.
- dqh 3y agoI’d be interested to know if NakedJSX works for you. I released it about 6 hours ago and I'm looking for feedback. It allows you to use JSX (without React) to generate static HTML, and also to create DOM nodes in client JavaScript, and without any of the client side ‘framework’ stuff of React. You have full control over what happens when. https://nakedjsx.org/documentation/#getting-started https://nakedjsx.org/documentation/#getting-started EDIT: clarity
- caditinpiscinam 3y agoI think there's a niche for libraries that allow you to update the DOM declaratively without any requirements on how you manage state. My understanding is that React looks at props / hooks in order to diff the state of your app and selectively recompute the virtual DOM. An alternative is to naively recompute the entire virtual DOM. I think this is how Mithril.js does it? It may be less efficient for large apps but it lets you manage state however you like.
- ianbicking 3y agoI've been using Preact signals, which are also usable in React (though admittedly I haven't tried to use them). I've found them to be much more pleasant than useState (though I reflexively continue to use useState). I also use a pretty lazy pattern where I allow large portions of an application to rerender when state changes (implicitly by letting prop changes percolate through). For simple apps this works really well, and for complex apps it still works. Like I have an app with 200Mb of rendered DOM nodes that get rerendered from the root when anything changes, and it's totally fine. I wouldn't ship that app widely, but for internal use it's 100% fine.