[HN Gopher] Introducing react.dev
___________________________________________________________________
Introducing react.dev
Author : clessg
Score : 691 points
Date : 2023-03-16 19:11 UTC (1 days ago)
(HTM) web link (react.dev)
(TXT) w3m dump (react.dev)
| megous wrote:
| Nice demo of sluggishness of React:
|
| https://react.dev/learn/updating-objects-in-state
|
| https://megous.com/dl/tmp/zyrzbzjqxccvvdniorpj.webm
|
| (Top of the line desktop AMD chip.)
|
| The code has no transition, no setTimeout, no nothing that would
| indicate any delay. The dot should always be right under the
| cursor. This will happen with every similar UI pattern (want to
| resize something, move a slider, etc. etc.)
|
| I guess this is a result of tradeoffs React has to do by
| insulating people from DOM.
|
| There's probably some way to force immediate DOM update, but then
| you're pulling in a lot of useless diffing and checking for each
| frame, instead of just updating the single el.style.something
| property you'd do when directly using DOM API and leaving the
| browser to do the rest.
| herpderperator wrote:
| Apple M1:
| https://www.dropbox.com/s/ivz9hr2pcer5pt1/react_dot.mov?dl=0
| dmak wrote:
| If you're doing anything animation related, there is no point
| in using React's useState because it causes re-renders. The
| right approach here is to use useRef.
| andrewmcwatters wrote:
| This doesn't have anything to do with React, it has to do with
| refresh rate, vertical sync, and the fact that your cursor
| position is updated by hardware and doesn't undergo the same
| update process as the rest of UI compositing in an operating
| system.
|
| Draw a software cursor, and the same exact thing happens.
|
| In fact, in effect, the red dot is a software cursor.
|
| You can accomplish visualizing the same lag in a traditional
| update-draw loop in game software.
|
| Cursors are special. Sibling comments here don't experience the
| same effect, because they're running displays at higher refresh
| rates.
|
| That's it.
| mattgperry wrote:
| Your intuition is correct - there's nothing to indicate any
| delay.
|
| Look at your profiler. Notice any significant overhead? You
| don't.
|
| Implement this same thing using events and `.style` directly.
| You will get the exact same result.
|
| The pointerEvent => style feedback loop is unfortunately very
| slow, more or less so in different browsers/operating systems.
|
| Interesting that you would know so little about this and yet
| feel confident enough to make a proclamation like this is
| evidence of React's performance.
| senttoschool wrote:
| > _(Top of the line desktop AMD chip.)_
|
| Slightly off topic but my M1 Pro Apple Silicon Mac does not lag
| like your top of the line AMD chip.
|
| I know most consumers run React code with CPUs slower than
| Apple Silicon chips but this post is more of an endorsement for
| the M1 lineup.
| geodel wrote:
| This is relief. I was afraid that M1 Max would be minimum
| requirement for smooth experience.
| senttoschool wrote:
| I know your post is sarcasm but a base M1 would perform the
| same as M1 Pro, Max, Ultra in this case. It's the single
| thread speed that matters the most in web performance.
|
| So you just need an M1. The M1 Air is frequently on sale
| for $800 nowadays. Or if you're really on a budget, you can
| buy a used M1 Mini on eBay for $400. Very affordable for
| those who want high browser performance.
| jhugo wrote:
| Zero lag on my M1 MacBook Air too.
| ajkjk wrote:
| For anything like animation in React I would use CSS
| transitions or using direct updates on refs without triggering
| rerenders. It takes only a simple model of "what a rerender is"
| to understand that this is running potentially _way_ more code
| than it needs to for every update and injecting scripting
| frames before the actual animation update happens.
|
| So this should be `ref.current.style = {x: <whatever>, y:
| whatever}`. It's also a great use for useImperativeHandle() if
| it gets any more complicated. This is the example from the docs
| updated to use a ref: https://codesandbox.io/s/lucid-
| grothendieck-iquzfj?file=/App...
|
| On this example it pretty much looks the same, which I assume
| is because of what the sibling comment says, that any cursor
| drawn in software is going to be slower than in hardware, and
| the animation and app are trivial so the rerender is basically
| free. But this way is still better, and it'll be more obviously
| better if the components being animated are complex. There's
| not going to be any way to do it faster in JS, but React can be
| a lot slower depending on what happens on rerenders (which is
| often, if using imported components, somewhat out of your
| control).
| mmis1000 wrote:
| Do you have mouse that have much higher update rate than
| monitor? The mouse event frequency is generally capped at the
| update rate of monitor unless you use `pointerrawupdate` which
| will actually give you raw mouse event without delay.
| Rapzid wrote:
| There will always be the potential for lag because the OS UI
| thread is updating the native mouse pointer position separately
| from the browser UI thread updating the page.
|
| A similar issue occurs with native scrolling and fixed position
| elements whose positions need update every frame. You must take
| control of the scrolling in JS in order to prevent jitter.
| andrewmcwatters wrote:
| Well, bummer. I have a mature product using React Components
| which are now legacy. It looks like in the future, I'll slowly
| migrate these over to functional components, as is standard in
| the documentation.
|
| I'm disappointed by the fanatical adoption of hooks, but I saw it
| coming and I can't say their legacy documentation didn't warn me.
|
| I'm happy that other people seem to enjoy them without restraint,
| but obscuring magical details and making side effects seem like
| more of a big deal than they really are in programming seems like
| a design choice intended to infantilize engineers and shelter
| them from reality.
|
| I might finally invest some time into what it looks like to
| create front ends independent of any of the existing frameworks
| that exist today, which I think is probably controversial, but I
| want the decisions I make to last longer than the whimsy of
| engineering teams who don't care that they might change their
| mind in 10 years.
|
| I think having seen front-end software come and go so many times,
| I'd rather write some simple utility functions wrapping
| `Document.createElement()` and use native event handling.
|
| Too much fluff in front-end.
|
| I want the decisions I make to last decades, not just a few
| years. I don't think that's a sentiment appreciated by most,
| though.
| davnn wrote:
| Your will be surprised how nicely a functional approach with
| hooks can improve your frontend architecture. Side effects are
| the source of all evil, it's quite useful to take special care.
| andrewmcwatters wrote:
| I think the thing is that you're focused on this specific
| implementation detail of React. I just don't care. Not that
| you're not right, either! It's just a matter of competing
| interests.
|
| I'm running two businesses with a third on the way. I have
| bigger problems than people reinventing stuff with no
| benefits compared to what we were doing 20 years ago.
|
| I'm writing software every day, so I'm still involved in
| front-line work, but I'm interested in being the level of
| productive most people aren't.
|
| So the bigger questions on my mind are things like, "What
| knowledge can I build up that doesn't become obsolete?" "What
| social effects drive adoption that endanger those goals?"
|
| Those are questions that have, at least immediately, very
| little to do with implementation details, and are questions
| that help me navigate whether to ignore new technologies all
| together, or when I identify something new when I decide to
| adopt it.
|
| A part of that is looking for cues from maintainers that say,
| "Hey, we care that you're shipping, and we're not going to
| endanger your labor spent learning our intellectual
| property."
| Aeolun wrote:
| Then you should use PHP. It's the only thing I've ever used
| where I could run decade old websites with a marginal
| number of changes.
| j-krieger wrote:
| Backwards compatibility with class components still exists.
| It will exist in the future.
| brundolf wrote:
| I don't think it's productive to throw out enotionally-charged
| words like "fanatical" and "infantalize" in these
| conversations.
|
| There are many valid complaints to make about React hooks, but
| I'm not really seeing those here. And I'm not seeing evidence
| that you've crossed chesterton's fence with them either.
|
| I'll criticize hooks all day, but for all their footguns, they
| provide a level of abstraction (and a simplicity of
| implementation for it) that's really hard to argue with. They
| let you break up reactive stateful code in maybe the most
| scalable way I've ever seen, and their contract with the
| outside world allows for some crazy optimizations on the
| framework's part. I think the team is onto something really
| special here
|
| Of course they're also easy to misuse, and they can be really
| "magical" until you fully grasp them. Those are problems the
| ecosystem will have to grapple with (and I know the core team
| is aware of them). Though the "magic" at least is due more to
| _weirdness_ and inversion of control than it is to actual
| complexity. Having a grasp on how they work, I feel like I
| wouldn 't have too much trouble implementing a basic version of
| the same system myself, because the primitives are ultimately
| not very complicated
|
| I believe hooks are really good bones for building UIs, and I
| think they'll last because of it, even though the surface
| developer experience has some warts for now
| andrewmcwatters wrote:
| I think it's sufficient to say that having been exposed to
| hundreds of thousands of lines of code across different
| industries and programming languages, I don't like React
| Hooks, and I don't even like them repurposing the word "hook"
| which is otherwise known as a trampoline in other programming
| language contexts.
|
| React Hooks, if anything should have just been called React
| Callback Queues.
|
| As for emotionally charged words, maybe it's not appropriate
| in the current zeitgeist to post without some degree first of
| self-censorship, but it's how I feel, so I'm going to say it.
|
| React Hooks were fanatically adopted, in my opinion. Side
| effects are a regular part of programming. I find it, thusly,
| infantilizing to hide those details.
|
| I wish people would stop this sort of thing, but if you want
| to say your part and that's how you feel, say it too.
|
| Edit: You've apparently even been downvoted for expressing
| this sentiment, which I hate on HN, because it's how you
| felt. I wish social sites wouldn't do this. No one should be
| able to invalidate that.
| brundolf wrote:
| > React Hooks were fanatically adopted, in my opinion
|
| It was one of those things where the ecosystem had to be
| unified, because a fractured ecosystem would have died. The
| React team said "this is the way we're going", and people
| followed along not because they were fanatical, but because
| that's the path that was set out. We can debate whether
| hooks were the right call for the core team to make, but I
| think it's incredibly uncharitable to say every library
| author who went along with it was just being "fanatical"
|
| > I find it, thusly, infantilizing to hide those details
|
| Software development is all about hiding details. The key
| is picking the right details to hide and not hide. Hiding
| details (ideally) lets users focus on the parts that matter
| to them, and gives the compiler/framework/system room to
| optimize the rest.
|
| In React's case, we got features like automatic batching
| (https://react.dev/blog/2022/03/29/react-v18#new-feature-
| auto...) and concurrent mode
| (https://react.dev/blog/2022/03/29/react-v18#what-is-
| concurre...) for free, without having to modify application
| code, because the application code was already abstracted
| enough that the framework could significantly change how it
| did things behind the scenes without changing the contract
|
| In terms of developer experience: I consider myself to have
| a fairly deep understanding of the browser platform, and a
| fairly-complete understanding of how hooks "really" work,
| and I'm still glad that I have React's abstraction layer
| most of the time when doing real work at my job. There are
| escape-hatches, as there should be, and the rest of the
| time I'm really very happy not to have to fiddle with all
| the bits when I just want to render another form and
| implement some business logic. I don't feel the least bit
| infantilized.
|
| There are things I don't love about hooks - mainly that
| they do things which should really be language-level
| features, and that causes some dissonance - but here's what
| I love about them:
|
| They expose a tiny set of primitives - pretty much just
| useState and useEffect (useMemo, useCallback, and useRef
| can be implemented in terms of these!) - which plug
| directly into the simplest, smallest side-effect-y things
| we need to be able to ask the React framework to do for us.
| And then, because these state and side-effects primitives
| have their own reactivity baked in, we can compose them
| into larger stateful/side-effect-y abstractions which
| _also_ have their own reactivity baked-in (unlike classes,
| unless those classes are full React components). We can
| build amazingly high-level, convenient abstractions on top
| of this amazingly minimal set of reactive primitives, which
| will always themselves be reactive, no matter what. And
| then the framework can break them back down into the
| primitives at runtime (in fact, it never sees anything
| _but_ the primitives), and schedule and re-order and do all
| kinds of nifty stuff with them without breaking contract,
| because the contract is tiny and elegant.
|
| In my experience that's unique and beautiful.
| hbrn wrote:
| > In React's case, we got features like automatic
| batching
|
| It's truly amazing how React team manages to present
| leaky abstractions as something that community should
| celebrate. Or maybe what's amazing is that community is
| gullible enough to buy that. That's exactly the
| fanaticism your opponent is talking about.
|
| Batching isn't a new feature (it's also not a React-
| specific feature). Looks like batching became more
| fragile with hooks, so they had to fix it later.
|
| But of course React team doesn't call it a bugfix. Meet a
| new _feature_ : "Automated Batching". Great marketing.
|
| It seems like you're saying that benefit of hooks is that
| they made it possible to solve problems caused by hooks.
|
| Which actually rings true: I found that React folks
| absolutely love solving problems, and they love React
| precisely because it provides a never ending source of
| _solvable_ engineering problems.
|
| Of course, since your engineers will always be busy with
| engineering problems, they will have very little time for
| product problems. So your product will suffer, but at
| least your engineers will be happy. They get to talk
| about so many cool things: immutability, hooks, batching,
| concurrency, memoization (ironically, the opposite of
| hiding the details). Given how expensive engineers are,
| it might be a fine tradeoff for some companies, though I
| personally would never want to work in those.
|
| Also, after taking a quick look at Dan's post on
| batching, it seems like their solution is a great example
| of leaky abstraction. Their intention was to batch
| _rendering_ , but they implemented it by batching _state
| updates_. Which means you can 't expect to read the new
| state right after you set it. As far as I remember, both
| Vue and Svelte also implement batching, but they don't
| suffer from such counterintuitive behaviors.
| paulryanrogers wrote:
| > Class components remain supported, and are documented in the
| Legacy API section of the new site.
|
| So they're still not breaking backward compatibility. Looks
| like you don't have to refactor until you need something that's
| only hooks based.
| azangru wrote:
| > I might finally invest some time into what it looks like to
| create front ends independent of any of the existing frameworks
| that exist today, which I think is probably controversial
|
| This is a great idea. Nothing controversial about it.
| andrewmcwatters wrote:
| You end up having to answer to people in interview processes
| that have fewer years of experience than you, and have
| written sometimes orders of magnitude less code than you, and
| wonder why you make "weird" decisions not knowing that those
| decisions have been made with a collection of exceptional
| experiences.
|
| Lots of engineers out there today who don't have a simple
| answer for, "So what happens when one of your dependencies no
| longer exists on the Internet for one reason or another?"
| Aeolun wrote:
| > So what happens when one of your dependencies no longer
| exists on the Internet for one reason or another?
|
| For this to be a problem would require it to disappear from
| both npm and Github simultaneously, and for none of our
| devs to still have it on their local machine so we can
| reupload it under a different name.
|
| Like, I didn't think about that until you wrote it, but
| coming up with an answer isn't exactly hard.
|
| I'd rather worry about things that are more likely to
| happen, like someone accidentally dropping the prod
| database tomorrow.
| andrewmcwatters wrote:
| And with Docker containers? And proprietary binaries? My
| point being, as you've proven in your reply, that most
| developers are going to only think of the most obvious
| cases.
|
| And when you're a prolific writer and you've experienced
| more than just npm and GitHub, you're going to run across
| a scenario that makes you start thinking about how your
| practices in one ecosystem don't apply everywhere.
|
| I own intellectual property composed of dependencies that
| can't be obtained anymore. Or two people in the world are
| the only individuals who are known to still have the
| dependency, but neither of them will supply it.
|
| What's your plan for depending on a SaaS who goes out of
| business? Is everyone experiencing that on a regular
| basis? No, they aren't. But then you do. Once. And it
| changes how you do everything later, because you no
| longer have the privilege of not thinking about it.
| Aeolun wrote:
| > My point being, as you've proven in your reply, that
| most developers are going to only think of the most
| obvious cases.
|
| I don't think you can draw that conclusion from the fact
| that the comment didn't contain all the information you
| expected.
|
| I don't think it's reasonable to expect people to think
| of and mitigate every potential problem that can occur.
| You focus only on those that are both likely, and will
| have a big impact.
|
| Will people that have experienced a vanishingly unlikely
| problem try to mitigate that from ever happening again?
| Sure. But I'm not sure if it's actually rational to do
| so, when they have bigger and more likely problems to
| worry about.
| azangru wrote:
| > So what happens when one of your dependencies no longer
| exists on the Internet for one reason or another?
|
| Can I rephrase it to something more realistic?
|
| "So, what happens when one of your dependencies is no
| longer maintained, for one reason or another?"
|
| or
|
| "So, what happens when one of your dependencies conflicts
| with a newer version of another one of your dependencies,
| which you are keen to update for one reason or another?"
| gratitoad wrote:
| It happens: https://qz.com/646467/how-one-programmer-
| broke-the-internet-...
|
| I'm by no means in the web-development-sucks-lets-kill-
| the-build camp, I think modern web frameworks and tooling
| can be incredibly useful particularly at scale (people,
| codebase, features), but JS dependency management is
| pretty nightmarish rn.
| stuff20230314 wrote:
| Decoupling your personal future from Silicon Valley devs'
| pursuit of promotions is always a great idea.
| FpUser wrote:
| I use some narrow scope libraries. Other than that I use plain
| JavaScript with Web Components. No frameworks. Saves me a bunch
| of time.
| motoxpro wrote:
| Picked up react in the last 5-6 years and looking at old class
| component examples confuse me to no end. I guess it's just what
| you learned first.
| Aeolun wrote:
| I worked with class components first. Built a whole app in
| them. Now we've migrated to functional and I look back at the
| class based ones wondering how I ever dealt with that.
|
| I didn't _want_ to adopt functional, but let everyone make
| their own decisions on what to use, and now I'm very happy I
| did.
| j-krieger wrote:
| Right. I don't understand the HN crowd. A Haskell thread
| every weak, tons of people arguing that <current year> will
| be the breakthrough of lisp on desktop, but they scream for
| OO patterns in their frontend frameworks.
| detaro wrote:
| So why do you scream for OO patterns in frontend
| frameworks?
| tome wrote:
| Possibly the screaming for different things is being done
| by different people.
| andrewmcwatters wrote:
| :) True. My first web development experiences were on AOL
| Hometown and reading people's 1337 scripts from
| dynamicdrive.com. DHTML! Updating PHP scripts over FTP!
| Shared hosting.
|
| Oh right, you meant React wise... yeah...
| chess_buster wrote:
| me too
| nmjohn wrote:
| > I want the decisions I make to last decades, not just a few
| years. I don't think that's a sentiment appreciated by most,
| though.
|
| Asking for an API interface to be stable for decades __across
| all future versions of the library__ doesn't sound realistic to
| me. Nothing is forcing you to update to the future new version
| of react - which has not been released, and is likely years
| away - that removes support for class components.
| hartator wrote:
| Basic HTML tags are more than 20 years old now.
| j-krieger wrote:
| Yet some are deprecated, Quite a lot don't work how
| specified and even more work differently depending on the
| browser you're using.
| umanwizard wrote:
| There are some you can't use anymore, like blink.
| [deleted]
| andrewmcwatters wrote:
| Well, one day you might branch out of front-end development
| and find that other subfields of software engineering are
| very different from what you know right now.
| nmjohn wrote:
| I've spent the vast majority of my career outside of front-
| end development. You're being extremely condescending and
| presumptuous so I will not engage further.
| andrewmcwatters wrote:
| My apologies. That was presumptuous. I just think of
| things like Unix and C interfaces and wonder where you're
| getting those ideas from.
| j-krieger wrote:
| The Linux kernel is literally the _only_ thing I could
| think of where you could argue as such.
| r3trohack3r wrote:
| FWIW this is exactly what I like about FreeBSD.
|
| For a lot of Linux distributions, you have a problem and
| you go online to find a solution. Depending on how old
| the stackoverflow (or w/e) answer is - the answers you
| find are out of date. So you find yourself sifting
| through a pile of possible answers and you need to figure
| out which answer applies in this context.
|
| Compare that to FreeBSD where it feels like every effort
| has been made to stay backwards compatible with the
| legacy APIs for decades. I found a web-book on FreeBSD
| network administration once and almost dismissed it
| because it was last updated in the 90s but, upon closer
| inspection, most of the book was still relevant and I
| could administer a FreeBSD network using the same
| commands the book was using!
|
| As an industry I do think we devalue tribal knowledge and
| the accumulated ecosystem of documentation that gets
| invalidated with every breaking change. Every time you
| ship a breaking change all of those hard learned lessons
| across all of your users that are sitting in the back of
| their gray matter, in their blogs, and in stack overflow
| answers all become invalid - at best they get
| removed/updated and at worst they stick around and
| mislead future adventures.
| CoolCold wrote:
| one of the reasons why Docker is so popular [among web
| devs] - it's basically the same inside and all that
| changing parts are handled by cloud in good case or by
| greybeard sysadmins in worst case.
| CTDOCodebases wrote:
| I have just repurposed a bunch of old computer parts into
| a low spec server running FreeBSD and I couldn't agree
| more.
| strokirk wrote:
| C#, C++, Python, Ruby, Java... change is rampant.
| nfRfqX5n wrote:
| React has been out for a decade. Why can't your system could
| stay on this version forever?
| andrewmcwatters wrote:
| I won't immediately update, since future feature development
| will take priority, but eventually I will want to update
| since the current industrial risk is that surrounding
| dependencies may have bugs that are a risk to customers.
|
| It's a low likelihood, but I'd rather stay up to date when I
| can.
| nagonago wrote:
| > front ends independent of any of the existing frameworks that
| exist today, which I think is probably controversial
|
| Not sure controversial is the right word, in fact I think it is
| quite a common sentiment among developers, especially those
| that originally come from back-end. The only problem is finding
| a company that is willing to forgo the frameworks.
|
| They do exist though. Here's a short list of companies that use
| vanilla JavaScript, most notably GitHub and Netflix:
|
| https://gomakethings.com/companies-that-use-vanilla-js/
| bdangubic wrote:
| funniest thing to me is how many people identify themselves as
| "react person" or "angular person" and I am thinking "you'd be
| better off saying you are "cobol person"
| rwalle wrote:
| You probably should have a better understanding of how hooks
| work and why they are better before posting a long and
| meaningless rant like this.
|
| There are things that you complain when you are junior, but
| start to understand better and realize why people do certain
| things in a certain way when you get more experience and can
| look at things from a higher viewpoint.
| hartator wrote:
| Yes, I have trouble getting what was wrong with the first
| stables of React.
|
| It seems they are getting bored.
| FactoryReboot wrote:
| Hooks were the beginning of the end of my interest in React.
| Truly a terrible concept. Way to magic. Not overly aesthetic,
| not to mention the async programming techniques the js
| community has developed for over a decade all kinda break down
| with hooks.
|
| You can't even just keep using class based as they have no way
| to consume hooks.
|
| Unit testing of hook based code is non existent IME. It's some
| kinda funky E2E feeling test.
|
| React was my favorite framework before. It's really a shame.
| SPBesui wrote:
| > Unit testing of hook based code is non existent IME. It's
| some kinda funky E2E feeling test.
|
| I'm guessing you're referring to the fact that you can't
| access component state like you can with class components. If
| so, that's not required to do a unit test. That's a sign that
| implementation details are leaking into your tests.
| motoxpro wrote:
| They are just so simple to me that the "magic" never comes
| into play. Just a function that gets called when something in
| an array is different between renders.
| reaperducer wrote:
| _I might finally invest some time into what it looks like to
| create front ends independent of any of the existing frameworks
| that exist today, which I think is probably controversial_
|
| Do it. Don't be afraid to, either.
|
| Over the years, I've put together a list of some big and VERY
| big companies whose web developers _hand-code_ their web sites
| without assistance from the framework-du-jour.
|
| I recently learned about a new one for my list: A nine-figure
| household name tech company.
|
| The list is useful for when I'm in bars or developer meetups or
| coffee shops and someone who's only been putting together web
| sites for a few years starts preaching about how whatever shiny
| new thing they just learned about in junior college is the one
| and only way to do things.
| gratitoad wrote:
| You tease. Dunno why you'd go out of your way to not name
| names, but it's working: Who?
| r3trohack3r wrote:
| This is exactly what I'm doing with my personal "framework" I
| use for client contracts. It's just Web Components with a handy
| class based wrapper. I call it Template, since it's based off
| <template> tags.
|
| It's a joy to work in, feels "frameworky" but it's just web
| standards with <100 lines of convenience JS wrapped around it.
| There is no magic beyond what the browser provides - I like it
| that way.
|
| https://github.com/retrohacker/template/
|
| It's "open source" as a reference. Just using it for myself.
| There aren't many docs beyond notes to myself. But the actual
| framework is a 90LoC JavaScript file that is an easy read.
|
| You're welcome to kick the tires. If you like it I'd entertain
| PRs and stuff but it's such a small library forking is probably
| entirely reasonable to make your own flavor too.
|
| The general idea is you extend the Template base class and call
| "super" with the id of the <template> that will get bound to
| the ShadowDOM when the class is mounted. Then you call
| instance.mount and pass a dom node to mount it into the DOM.
| For child nodes, you use `this.fragment.querySelector` to
| select them from the <template> you mounted. It supports
| garbage collection by tracking children, so when you "unmount"
| it recursively unmounts all child instances as well. Finally it
| has an event emitter implementation, so changes/actions/events
| bubble up the DOM while state can push down through the DOM.
| Keeps things clean.
|
| I recently added state methods since I was duplicating state
| management everywhere. Now the base template class has a
| `setState` that will emit a single `change` event for all
| changes in the current "tick" of the browser eval loop.
|
| Cheers and happy hacking!
| bnert wrote:
| This is cool! Small and no magic.
| koch wrote:
| I like how for your brief documentation you start with a
| single index.html file. Too many web/framework docs start
| with a command that gives you a directory full of who knows
| what, which tends to negatively affect beginners more than
| anyone
| samtho wrote:
| I can pinpoint the exact time where I fully became
| disillusioned with front end work and it was the day where
| I realized that in order to be productive with these tools,
| you had to set it up with the CLI.
| r3trohack3r wrote:
| A lot of these frameworks don't actually need a CLI to
| scaffold them. React was (at least originally, I haven't
| checked in on it in a while) designed to be
| _incrementally_ adopted so you can retrofit an existing
| website with React components.
|
| But I do agree with the CLI for bootstrapping being a
| problem for react. It's less of the CLI itself and more
| of the mountains it moves under the hood to setup the
| app. I run a single command and get an absolutely massive
| project. Yes the final dist file is only KBs in size, but
| the entire build process that gets scaffolded is still
| part of my project. That single command install seems
| "easy" but leaves me with a huge amount of existential
| dread - no matter how much the tooling "paves the path"
| it doesn't delegate responsibility. Ultimately I'm on the
| hook for this application and when things don't work it's
| on me to understand why and fix them. After a CRA
| install, I'm often left feeling like I'm looking off a
| cliff into an abyss that is going to take a huge
| investment to understand.
|
| The last time I used React was inside a big company. I
| felt safe using it there because there was a team
| responsible for "owning" react inside the company. I
| followed their docs to start with CRA and pull in their
| component library. If anything inside my CRA app went
| sideways I _had_ delegated responsibility to another team
| for that, I had a support line that I could reach out to
| to get help and ultimately problems at that level were
| their responsibility. That isn't true in my personal
| projects - so I don't use it there.
|
| FWIW I actually feel the same way about infrastructure
| components. I am Terraform certified, have been
| sysadmining Linux installs for over a decade, have built
| a serverless platform inside FAANG, played SRE, etc. But
| still K8S, Linux, etc. leave me with similar feelings.
| When I can delegate their responsibility I'll build on
| top of them or participate on teams that manage them, but
| for my own stuff there is too much to chew for me to
| adopt that for a personal or client project. Even with my
| background, for my projects I choose platforms where I
| can delegate that part of the stack to a vendor. These
| days I'm building on Cloudflare Workers, R2, and
| PlanetScale for my DB (until D1 is prod ready). When I
| adopt a service - I pay for it at a rate that gets me
| support contracts. That $$$ is funding an engineering
| team far greater than me to build, support, maintain, and
| understand that chunk of the system so I don't have to.
| conradkay wrote:
| I just swapped my app to Vite from CRA and it's far
| better. CRA was pretty simple too especially if you
| weren't using typescript, I assume you were post "eject".
| arcanemachiner wrote:
| I remember the first time I set up a React app in
| 2015-ish and pulled in like 300MB of dependencies to do
| some basic tutorial.
|
| I will never forget the visceral disgust I felt in that
| moment.
| jdthedisciple wrote:
| Great project, exactly what I've been looking for - a _truly_
| minimal JS "Framework*!
| r3trohack3r wrote:
| Glad you like it! Feel free to take it and make it your
| own.
|
| If you make changes, I'd appreciate a follow up GitHub
| comment that lets me know where you made improvements, but
| no obligation. It's licensed under a BSD-style license so
| you're free to do with it whatever you like!
| DrVanNostrand wrote:
| Simple, but folks moved on from Backbone-like UI libraries
| for good reasons.
| r3trohack3r wrote:
| Would love to hear feedback! What are those reasons and how
| do they apply here?
|
| I've used React and Storybook quite a bit - this was
| inspired by those experiences. Haven't used Backbone in
| over a decade.
| andrewmcwatters wrote:
| Cheers, kudos to you for writing long lasting software.
|
| Edit: Hey another Arizona hacker! Right on!
| r3trohack3r wrote:
| Right on!
|
| Just checked out your website. I'm also doing Software
| consulting in Arizona, would love to grab coffee (digital
| or otherwise) and compare notes.
|
| If you are in the PHX area, checkout
| https://www.heatsynclabs.org/ - they do Coffee & Code every
| Wednesday.
| chirau wrote:
| And beat Princeton today. :)
| smithcoin wrote:
| Whoops.
| thefreeman wrote:
| oops
| triyambakam wrote:
| This is awesome! I was actually looking for this very kind of
| thing the past couple of days. I was searching HN and Github
| for "vanilla js" and various "framework" queries but not
| finding anything. Thanks!
| eurasiantiger wrote:
| Watch out for the Web Component gotchas, though: the shadow
| DOM encapsulates the CSS cascade meaning your styles will
| not apply to your components unless you explicitly apply
| them to each one. Also, events don't automatically bubble
| up!
| mhoad wrote:
| It's actually not a huge deal in practice.
|
| I just put together a content style website using nothing
| but web components and used a base class to put my global
| styles into and just inherited my various components from
| it.
|
| Was also really easy to factor out shareable styles like
| various page layouts using a similar technique.
|
| That just left me with doing small targeted tweaks where
| I would override things with custom properties along the
| way as needed plus any component specific styles.
|
| Was probably the cleanest approach I've had in as long as
| I could remember. Plus it was delivering me a perfect 100
| score in Lighthouse too for what it's worth. Would
| recommend.
| fndex wrote:
| > I want the decisions I make to last decades, not just a few
| years. I don't think that's a sentiment appreciated by most,
| though.
|
| Clojure and ClojureScript very much appreciate that sentiment.
| re-frame, a library for creating React apps with ClojureScript
| is rock solid, many years old, and still on version 1, meaning
| no breaking changes so far. 5 years old re-frame code still
| looks the same today.
| koito17 wrote:
| I use re-frame, but you cannot deny that class components
| being deprecated is going to be pure trouble for re-frame.
| Re-frame relies on the reagent library's Reaction interface.
| While re-frame does not depend on anything else in the
| reagent library, it is natural to use Reagent for your
| rendering. But reagent itself emits class components by
| default, since it predated hooks by several years.
|
| Now that class components are essentially deprecated in the
| documentation, and the fact that React 18 support is _still_
| an experimental feature in Reagent, people using
| ClojureScript and React today are in quite some trouble,
| especially since React is the only JS framework I know of
| that is compatible with functional programming.
|
| While reagent is able to emit function components, there is a
| performance penalty to this, since it employs some hacks in
| order to be compatible with both hooks and ratoms. Thankfully
| there are some projects that are attempting to bring modern
| React[1] and even bring the whole re-frame API alongside
| it.[2]
|
| Last weekend I decided to try out helix, refx, reitit, and
| shadow-cljs' lazy-loaded modules and managed to make a pretty
| nice demo app that uses essentially _the_ re-frame API but it
| 's all modern React and hooks, and the router was capable of
| lazily loading modules containing code of pages the user
| wanted to navigate to.
|
| [1] https://github.com/lilactown/helix
|
| [2] https://github.com/ferdinand-beyer/refx
| bakugo wrote:
| > seems like a design choice intended to infantilize engineers
| and shelter them from reality.
|
| The entire front-end framework landscape is like this. It's all
| designed to appeal to the kind of "engineer" that just wants to
| copy paste code and have it work like magic without ever
| thinking about what's actually going on.
| strokirk wrote:
| That sounds just like me and my backend coding too! What are
| you doing to justify being to high and mighty?
| robertoandred wrote:
| It's hilarious how frontend engineering is both for dumbdumb
| fake engineers while also being too complex for vaunted
| backend engineers to understand.
| kingboss wrote:
| No. It's not too complex. It's just boring. And you people
| keep reinventing the wheel and presenting old concepts as
| "revolutionary" or "innovative". That is why you get looked
| down upon.
| MrOwnPut wrote:
| Or you don't understand the needs or the technology
| because of your stubbornness and ignorance.
|
| That's why I look down upon engineers with your mindset.
| I won't generalize all backend engineers as you did to
| frontend though.
|
| I've met many who get it but of course prefer the
| peacefulness of controlling the execution environment and
| the limited state of a server.
|
| Btw imo backend is boring because the reasons above,
| frontend has a lot more going on. As a full stack
| engineer I'd say frontend is much much harder, and that's
| why you have all the tech trying to make it easier to
| scale and maintain. That's not to say backend doesn't
| have it's own difficulties. It all depends what you are
| making too. A website is easy, a complex app is much more
| difficult.
| kingboss wrote:
| I didn't say I look down upon frontend devs. I said that
| because of the way frontend seems to be chasing trends a
| lot of people look down on you. Maybe I should have said
| "That is why you get looked down upon by a lot of
| people".
|
| Why are you assuming I am a backend dev? In fact why do
| you even assume I do web dev? You do know that there are
| many more areas where programming is needed, right?
| MrOwnPut wrote:
| Do you have the same judgement you invented or would you
| like to mind read other's opinions and generalize groups
| of people some more?
|
| How I took that is you just don't want to commit to your
| own statements, so you speak through these "others"...
|
| And backend isn't just web. I was using a catch-all to
| call out how, misinformed, ignorant, and offensive your
| statement was.
| yawnr wrote:
| The only people who look down on frontend or backend
| engineers are people who don't understand what it means
| to be great in either domain, and are too arrogant to
| take the time to learn and appreciate its nuances.
|
| Every engineer I've known who's "looked down" on frontend
| or was dismissive of it was not only _bad_ at frontend
| and didn't understand what it takes to be good at it, but
| also a jerk about the perceived depth of their own
| knowledge.
| robertoandred wrote:
| Do you write in assembly?
| kingboss wrote:
| Very rarely. Hmm, I don't think I wrote assembly in the
| last few years though. Why?
| r3trohack3r wrote:
| I don't think this is a truly irreconcilable stance and I
| don't think it's exclusive to frontend, you run into it up
| and down the stack.
|
| I think there are two approaches to software development,
| and a gradient of people transitioning between them:
|
| (1) I'm responsible for this system and I either have to
| understand this well enough to feel comfortable being
| directly responsible for it or delegate responsibility
| through my org structure or vendor contracts.
|
| (2) I don't understand how any of this works, it's just a
| bunch of magical incantations that get me results, and one
| incantation is interchangeable with another.
|
| Your dumbdumb fake engineer isn't a fair characterization
| of (2) but I do believe a lot of tools in a lot of
| ecosystems are optimized for engineers without the depth of
| knowledge necessary to operate them under the API contract.
|
| That's totally fine when that API contract is provided by a
| responsible party you can delegate responsibility to. The
| problem comes in when you provide these "simple" API
| contracts on top of extremely complex internals and hand
| them to a developer/user who is ultimately responsible for
| the entire stack, internals and all.
|
| In some cases (2) can offset risk using a "cattle" approach
| where multiple live versions of the system are kept up,
| changes happen one at a time, and you can fail over if
| something goes wrong and throw away the old state. I've met
| engineers who operate K8S clusters this way. They are
| clearly out of their depth with kubernetes, but they can
| fail over to a secondary and rebootstrap a bad cluster from
| scratch to get back to a good state. By keeping things
| disposable you exclude most (all?) failure modes other than
| "poison pill" bugs that repeatedly put your system into a
| bad state.
|
| But, for the most part, these complex open source systems
| that try to hide complex internals give the illusion of
| delegating responsibility. You might get pretty far before
| an incident comes knocking and it's time to pay the toll.
| nailer wrote:
| This is exactly the "just use react" stereotype. Download a
| random react component from NPM and 90% chance they just
| added wrapper divs until they could get the CSS to (kind of)
| work.
| andrewmcwatters wrote:
| It's just front-end engineering in general, you don't get
| this with people who work in other subfields of software
| engineering. I get it, though. It's OK until you need to
| learn and grow beyond it, which I think anyone doing this
| long enough will.
|
| It sucks that people learn this the hard way, though, and the
| only way to grow beyond this for people new to the field is
| to eventually get burned and learn there are other ways to do
| all of this.
|
| There are whole generations who don't know what session
| cookies are! And... that's just OK.
| Aeolun wrote:
| > There are whole generations who don't know what session
| cookies are!
|
| I really enjoy JWTs, but the idea of sending all my user
| data on every request hadn't occurred to me, and still
| feels mildly wasteful.
| andrewmcwatters wrote:
| Generally a session cookie requires that you send over a
| unique ID. That's usually it. If you use JWTs, you're
| sending over the same amount of data if not more, but now
| you have to do things yourself instead of just utilizing
| features browsers natively have.
|
| You could utilize a key system to gain the same advantage
| as not having to use persistence as one gets using JWTs
| when implementing session cookies, if you wanted, too.
| tut-urut-utut wrote:
| What's wrong with that?
|
| Let's better spend time on important things instead of
| wasting time trying to make UI behave properly across a
| plethora of browsers, OSes and platforms.
| azangru wrote:
| > instead of wasting time trying to make UI behave properly
| across a plethora of browsers, OSes and platforms
|
| Cross-browser compatibility was the problem that jquery was
| trying to solve back in 2008 or thereabouts. Not a problem
| that react is trying to solve in 2023.
| epolanski wrote:
| And yet the sanest option for this, web components, keeps
| struggling.
| r3trohack3r wrote:
| I've been using WebComponents a lot lately.
|
| My biggest gripe with them as a technology is that they
| have no way to associate a `<style>` tag in `<head>` with a
| ShadowDOM tree (short of cloning and injecting w/ JS).
|
| The only way to say "this CSS goes with this <template>" is
| to nest the `<style>` tag in `<template>` itself or
| painstakingly expose `part`s on everything you want to
| style.
|
| I'd really like a template selector for CSS where I can say
| something like `::template(#id) button` to select all
| buttons inside the `<template id="id">` for whatever
| ShadowDOM it is mounted to.
|
| Without this, I either have to do CSS in JS, CSS in HTML,
| or I have to use special build magic to take my standard
| index.css files and inject them into my HTML or JS. All of
| that is kinda gross.
| epolanski wrote:
| That's how it is intended to work to avoid that using two
| web components on two different websites leads to major
| inconsistencies because the root shares several classes.
|
| If you want to support your case, you either inject css
| or you design your web components to support css
| variables which pierce throgh the shadow dom.
| conradkay wrote:
| Sounds reasonable and like good code and design, perhaps we
| "engineers" think hard enough already. I just started reading
| A Philosophy of Software Design and it talks about "deep"
| modules (they give the example of UNIX's open creat close
| lseek and read vs java's I/O interfaces).
| Rapzid wrote:
| The docs are kinda poor on them IMHO. They don't approach the
| hooks from first principles. For example look up the
| useImperativeHandle hook docs. Use those to explain simple
| questions:
|
| > Why do you need this?
|
| > Why can't I just update the ref however I want!
|
| Look up forwardRef:
|
| > Why can't I just access ref as a prop?
|
| Further, everyone is trying to cram all logic into hooks and
| components. It's to the point of insanity. Look, React is so
| popular I know most are using it for throw away marketing sites
| and other low-tier shit (sorry y'all but you know it) but..
| This architecture doesn't fly in large apps; ee b2b etc.
|
| React Router v6 seems to have no non-hook based APIs that
| aren't marked private!? They screwed the pooch on
| useNavigation; it causes unnecessary re-renders. Surprise
| surprise, but if they can't get it right...
| jholman wrote:
| > React Router v6 seems to have no non-hook based APIs that
| aren't marked private!? They screwed the pooch on
| useNavigation; it causes unnecessary re-renders. Surprise
| surprise, but if they can't get it right...
|
| Whoa, you lost me here. React Router is no shining beacon of
| good API design. They've never done things well, just "well
| enough". I'm not saying RR is _terrible_ , I'm not saying the
| RR devs should _feel bad about how bad they are_ or
| something, I 'm just saying that these guys are not the guys
| you want to point at for "if they can't get it right...".
|
| (Example of RR being not-so-amazing: Initially (v1? v2?) they
| required you to use attributes for the components that would
| render in a route, with no way to specify props short of
| making a custom component that wrapped the one you wanted.
| Then they added the ability to pass a function as an
| attribute, which let you specify props, so that was usable
| but clunky. Then, in yet a third version of the API (I think
| this is by v4?), we got the ability to use JSX in children to
| fully specify the components, which obviously was the right
| choice all along, it's literally the point of JSX. And again,
| I'm not saying I'm a better software engineer than those
| guys; I think I'd have got this one right but I'm sure I'd
| have screwed up a dozen other things.)
| Rapzid wrote:
| I'm not going to argue with any of that but:
|
| * It is the de facto "official" community router solution
|
| * It's made by the same team as Remix..
| robertoandred wrote:
| You call other devs "infants" but are unable to understand how
| hooks work. It's really not complicated under the hood.
| epolanski wrote:
| I'm slowly trying to get most of my projects and client ones to
| leverage more and more web components, I'm sick of
| reimplementing the same things over and over.
| codeptualize wrote:
| And then we have another framework! This is why we have so many
| :D
| ojkelly wrote:
| > Well, bummer. I have a mature product using React Components
| which are now legacy. It looks like in the future, I'll slowly
| migrate these over to functional components, as is standard in
| the documentation.
|
| The writing has been on the wall for 4 years that hooks are the
| future. You _can still_ use class components. Function
| component with hooks is the simplest API you can get to React
| itself--classes are more of an abstraction.
|
| > I'm disappointed by the fanatical adoption of hooks, but I
| saw it coming and I can't say their legacy documentation didn't
| warn me.
|
| We all adopted hooks because it makes things easier to reason
| about. If you're still having trouble understanding them, I'd
| urge you to dig deeper into how they and React works.
|
| > I might finally invest some time into what it looks like to
| create front ends independent of any of the existing frameworks
| that exist today, which I think is probably controversial, but
| I want the decisions I make to last longer than the whimsy of
| engineering teams who don't care that they might change their
| mind in 10 years.
|
| I can't think of a better way to develop an appreciation of UI
| frameworks that to go without.
|
| > I want the decisions I make to last decades, not just a few
| years. I don't think that's a sentiment appreciated by most,
| though.
|
| Barely any software runs untouched for decades (documents don't
| count). So it's not that the sentiment isn't appreciated, I
| think most of us would agree--it's that it's an impractical
| expectation.
| andrewmcwatters wrote:
| When you maintain your own software for periods of time that
| outlast front-end engineering trends or IC's entire career
| tracks, your opinions might change.
|
| Plenty of software runs untouched for decades. A lot of it
| powers your interactions with people on HN right now, from
| drivers, to font rasterization and backing layer UI
| composition. There are bugs in codebases that have taken 20
| years for people to even notice. It happens.
|
| When people don't have to worry about trivial details, they
| can focus greater efforts.
| j-krieger wrote:
| And yet, I've said no to projects that would've earned me a
| nice sum because they were started at a nice pace with a
| dev that intended to build his own frontend framework, and
| it slowly grew into an eldritch horror.
| jzombie wrote:
| I feel that. I have even done that myself.
|
| Typically written by folks who aren't even aware of the
| problems they are trying to solve, no tests, and event
| and timer leaks.
| ojkelly wrote:
| I've been around this space for over a decade. Software
| that's easy to change, tends to outlive the rest.
|
| React has more staying power than almost any other JS
| library I've seen. And they've maintained backwards
| compatibility on par with Windows.
|
| The other day dang was mentioning how HN struggling under
| the popularity of the GPT4 thread[0]. But even then, surely
| HN has seen some code updates. If you look at HN as a
| product (and not a codebase), the unofficial/official
| algolia search engine is an addition.
|
| What runs untouched for decades?
|
| [0] https://news.ycombinator.com/item?id=35157344
| lelandfe wrote:
| At once I sympathize with your viewpoint and also have to
| say that React is the longest I've ever seen a Javascript
| thing stay in the notoriously fickle good graces of the
| frontend world - short of perhaps jQuery.
|
| Railing against it is railing against the best-in-class
| example of what you want... even if it still falls short of
| what you want. A decade is nothing to sneeze at.
| mattmanser wrote:
| But it hasn't really lasted has it?
|
| We've had React 1 (components) and now React 2 (hooks),
| they just managed the transition better than angular and
| so gobbled that market share.
|
| jQuery stayed mostly stable, there was only one version
| that I can remember where it was a bit of a hassle to
| upgrade it. But it's quite a while ago now, so could be
| mis-remembering.
| ojkelly wrote:
| It has lasted as a project. Are you saying that no
| library should try to improve their performance,
| internals or API?
|
| There was many versions of jQuery. I remember the days of
| hacking Drupal to load multiple versions because it
| shipped with an older version, but we needed a newer one
| for other dependencies.
| andrewmcwatters wrote:
| Right, exactly. Had Angular.JS slowly implemented what is
| now just Angular, they wouldn't have displaced so many
| people so fast.
|
| I think it still would have happened, but it's a
| shortsighted read into competitive analysis to not
| understand how this happened.
| [deleted]
| pdntspa wrote:
| I've got a multi-gigabyte folder of portable windows programs
| and utilities, where parts have been untouched for 15+ years.
| For the most part, everything still runs.
|
| Winamp? Check.
|
| Spacemonger? Check.
|
| FLAC encoder? MP3 encoder? Notepad++? Savihost? TheGodfather?
| Flash Player? MS XML Notepad? ConEmu? Some really old build
| of CockroachDB? CPU-Z? Doom Builder 2? HexChat? Hell, even
| mIRC? Check check check check check checkity check.
|
| None of those have been updated in _years_ , many untouched
| (but not unused) since the day I installed them. This is why
| the web is so effing stupid. (And a hat tip towards Microsoft
| for keeping promises, unlike web developers)
|
| And in many cases they STILL work better than the crappy
| little my-first-webapps that everyone uses instead nowadays.
|
| Software is and should be eternal. It's these damn platforms
| that nobody wants to hold still with.
| stickfigure wrote:
| I used to use a few of those programs you mentioned. I
| moved on to other programs that solved my needs in better
| ways.
|
| They could have stopped changing React. And people would
| have moved on to other things.
| pdntspa wrote:
| > They could have stopped changing React. And people
| would have moved on to other things.
|
| God I wish!
| FactoryReboot wrote:
| I strongly disagree. It was way easier to reason about things
| pre hooks.
| SPBesui wrote:
| I think you're probably referring to the lifecycle methods,
| which have relatively clear and unambiguous names in class
| components. The thing is, those names may make you feel
| comfortable that they do what their respective names imply,
| but in reality they're an abstraction away from how React
| really works under the hood. Hooks, for better or worse,
| get you a little "closer to the metal," so to speak.
|
| Also custom hooks are vastly more readable IMHO than HOCs.
| Varqu wrote:
| As a programming newbie, I would love to see a hard fork of
| React without Hooks (and their magic)
| web3-is-a-scam wrote:
| check out Preact and Inferno
| easrng wrote:
| I love preact but it definitely has hooks.
| web3-is-a-scam wrote:
| good to know, it's been a while since I've used it (moved
| on to htmx for my uses mostly) and a quick look on the
| homepage still espouses use of setState and class
| components.
| xdennis wrote:
| > obscuring magical details and making side effects seem like
| more of a big deal than they really are in programming seems
| like a design choice intended to infantilize engineers and
| shelter them from reality.
|
| You seem to be taking it too personal. There's no need to call
| others infants for preferring hooks.
| [deleted]
| groestl wrote:
| > `Document.createElement()` and use native event handling.
|
| I'm not a frontend dev by all means, but I must say, I've
| worked on such projects (100LOC create utils & event handling)
| and it was a joy. I always wanted to recommend it to people
| when they complain about the state of js frameworks, but I felt
| I've no authority to do so, because my experience is limited
| (only internal projects).
| Aeolun wrote:
| But have you built whole applications in them? React is one
| of the few frameworks where I almost never feel like they
| didn't consider consider all use cases.
| [deleted]
| timcobb wrote:
| Not seeing where it says that classes aren't going to be
| supported anymore
| mwcampbell wrote:
| > seems like a design choice intended to infantilize engineers
| and shelter them from reality
|
| I think it's more charitable to assume that the designers are
| designing this for themselves and are just being aware of their
| own fallibility and limited mental capacity (we're only human
| after all), not seeking to infantilize or shelter some lesser
| class of programmers.
| explaininjs wrote:
| Eh... having worked with a Facebook developer tools team,
| they quite literally do dismiss the vast majority of the
| engineers at the company as " _those guys_ who wouldn 't be
| able to understand the stuff _us devtools people_ do ".
| dxchester wrote:
| Agreed that investing in standards is always a good bet. But at
| the same time, we have so many web frameworks in part _because_
| what is spec 'd in plain JavaScript/HTML/CSS is not quite high-
| level enough to be really be a productive foundation just on
| its own. Going all the way back to raw `Document.createElement`
| will come with its own special pain.
|
| With the WebComponents movement though, we are getting ever
| closer to being able to rely on native browser functionality
| for a good share of what frameworks set out to do. We're not
| all the way to bliss without frameworks, but for what it's
| worth here is my 481-byte library to support template
| interpolation with event binding in order to make WebComponents
| pretty workable mostly as-is: https://github.com/dchester/yhtml
| atsjie wrote:
| > I want the decisions I make to last decades, not just a few
| years
|
| New to frontend?
| leros wrote:
| I'm usually the guy who is several versions behind on every
| library and I stick with what I know instead of exploring new
| features. I will say that React has been pretty pleasant to
| work with in regards to not forcing me to rewrite my code much.
| They're pretty good about keeping the old methods around our
| several major versions so you have plenty of time to make
| changes to your app or just keep doing things the old way.
| pupppet wrote:
| Another feather in Tailwind's cap.
| danabramov wrote:
| Haha :)
|
| For what it's worth, the site has been developed by different
| people over time, so the choice to use Tailwind was made by
| someone else early on. The team working on the site now doesn't
| feel strongly about it either way -- it's sometimes annoying
| but overall using it feels really nice! And I'd probably say
| the same about other CSS solutions too.
|
| I think we'll keep it for now. Where it really shines IMO is
| fast prototyping. But yeah, it's cool.
|
| Edit: Ok ok tbh I do _like_ it.
| benatkin wrote:
| Doesn't appear to be using Docusaurus. Interesting.
| slorber wrote:
| Docusaurus maintainer here. Wrote a Twitter thread explaining
| why Docusaurus is not a good fit in this case. https://twitte
| r.com/sebastienlorber/status/14527225683902218...
|
| Old but still relevant.
| starkparker wrote:
| Of course they don't. Docusaurus still doesn't support MDX
| v2, so they'd be stuck on React 17.
| danabramov wrote:
| Docusaurus is a fine project, but we thought it is
| important to use React _very_ directly -- so that we have a
| good sense of what it feels like to make an app with React.
| starkparker wrote:
| Awesome. So now that this has rolled out, can you all
| help the Docusaurus team figure out how to migrate from
| MDX v1 to MDX v2, and why it's been so difficult? It's
| been six months of work and it's to a point where we're
| considering moving off a React-powered docs solution
| altogether so we can unblock the rest of our app from
| getting off React 17.
| slorber wrote:
| Sorry from the Docusaurus team.
|
| It's taking a long time because there are edge cases to
| figure out if we don't want the upgrade to be painful for
| certain sites, notably the ones using anchor links or
| i18n. It's not far from the end so hopefully mdx2 will be
| merged soon.
| [deleted]
| isntbilly wrote:
| F
| jerrygoyal wrote:
| People tend to overuse Effect, this article explains it well
|
| https://react.dev/learn/you-might-not-need-an-effect
| sibeliuss wrote:
| I was praying for some kind of page dedicated to React Server
| Components. But alas.
| mattcarrollcode wrote:
| What would you like to see from a React Server Component page?
| sibeliuss wrote:
| How a team who isn't Next.js or Shopify can implement in
| their own frameworks, without needing to dig into Next.js
| sourcecode. The example app released around the announcement
| is quite old and bare-bones, and I'm sure there have been
| learnings and other guidelines since then. In short, it would
| be great to have a little more than a spec and an
| undocumented webpack plugin to work from.
| rrishi wrote:
| Whatever needs to be there for a new react dev to learn about
| them
| rrishi wrote:
| +1
| danabramov wrote:
| Not yet, but as the blog post notes, it's going to be a bigger
| focus now that the first integrations are in progress. For now,
| we've added a tiny bit about them here:
| https://react.dev/learn/start-a-new-react-project#which-feat...
| sibeliuss wrote:
| That's exciting news. As mentioned below, it'd be great to
| have some implementation steps for companies and projects who
| aren't at the Next.js framework technical level. There must
| be some middle-ground!
| debacle wrote:
| I like classes because they're easier to code review and easier
| to read/reason about. The artifical limitations are good. At a
| large org that's way more important than initial write.
| Diggsey wrote:
| All of the new documentation is horribly laggy in Firefox and all
| of the code sections are broken (eg. the visible cursor position
| does not match the actual cursor position...)
|
| This is latest stable Firefox on a high spec Windows 10 laptop.
|
| Not a great look given what React is supposed to do!
| romanhn wrote:
| Kudos to React maintainers for their focus on documentation. A
| year ago I decided to learn React and the official docs were
| instrumental in getting me up and running. For context, last time
| I'd done any serious coding was when I still had to care about
| IE6 compatibility, so all the modern SPA paradigms had to be
| picked up from scratch. I spent the afternoon reading the docs
| and was able to jump right into coding a basic proof-of-concept
| app that same day. The clarity of writing, the progression of
| topics, it all hang together very well. Looking forward to the
| latest iteration here!
| jve wrote:
| Its like 2 weeks since I had to grasp react, fluentui, react
| hook forms, webpack and a little more when I started using
| modules and even more when I used typescript.
|
| React clicked really fast, documentation new and old, articles
| helped get on track really fast.
|
| Wiring that all together and taming CRA (Create-react-app) with
| react-app-rewired to add stuff to webpack, like adding
| libraries to behave like modules that are NOT modules, packing
| all with scripts into single html, understanding where are
| boundaries between fluentui and react (both new to me), setting
| up monorepo because I separate reusable components from app
| itself and libs, applying css which I am bad at and stuff like
| that took more time... complexity just explodes, but less
| "mental effort" overall achieved by having streamlined build,
| reusable stuff etc.
|
| Otherwise I feel that building app with react takes a lot of
| "mental effort" away, because you develop a component in
| isolation which feels simple and when you use that component
| you don't think about implementation details - it is nicely
| abstracted away and things just work.
|
| Ah, yes, and I'm lucky I got the signal that functional
| components are way to go and the only place I had to use a
| small class component when I want to have a component variant
| for existing class based component from FluentUi where generic
| types are important and used within `onRenderItem` and various
| methods:
|
| > class LookupBaseInternal extends
| BasePicker<ILookupResultProps, ILookupPropsInternal> {}
| IceDane wrote:
| Just FYI - I would not use CRA. Even the react maintainers
| basically recommend you don't use it, since it's not really
| up to date with best principles, and they might eventually
| change it so that it becomes a wizard that lets you choose
| between other more modern choices like nextjs or vite.
|
| You probably want to look at vite for a more direct
| alternative to CRA. No need for things like -rewired, and
| it's probably 10x faster than CRA.
| solarkraft wrote:
| Back when I did an Angular project, throughout the day
| Webpack would fill up my RAM so hard that my M1 Macbook
| (with 8GB of RAM, connected to a 4K display) would
| eventually crawl to a halt and crash.
|
| No such issues with Vite. It feels super light weight,
| snappy as hell and can run forever.
| Cthulhu_ wrote:
| The new docs make no mention of create-react-app anymore
| either: https://react.dev/learn/start-a-new-react-project
| jve wrote:
| Oh, here is another 1 I caught:
|
| > There is currently no way to write an error boundary as a
| function component. However, you don't have to write the
| error boundary class yourself. For example, you can use
| react-error-boundary instead.
|
| https://react.dev/reference/react/Component#catching-
| renderi...
| intellix wrote:
| You can pretty much skip React and go straight to Qwik as it
| solves N+1 and it fixes the ability for low quality devs ruining
| perf with useEffect since you have signals ala Solid
| nayroclade wrote:
| Unbelievable that they've gone ahead launching this, going all in
| on hooks, while the fundamental problem with them, which was
| raised in _2018_ is still unsolved:
| https://github.com/facebook/react/issues/14099
|
| And they just handwave it away in the docs with an imaginary
| future API. Embarrassing.
| chatmasta wrote:
| And yet, entire startups have been created and acquired during
| that time, many using React and many using hooks. It appears
| this "fundamental problem" is far from a show-stopper.
| Ultimately, that's why people like React: it gets the job done.
| The API is small and extremely stable. The last major breaking
| change was hooks, and that wasn't really even a breaking change
| - just a new paradigm that you should move to eventually (class
| components _do_ still technically work!)
|
| Honestly, by the time class components are fully deprecated,
| you'll probably be able to ask ChatGPT to rewrite your codebase
| to use hooks instead...
| epolanski wrote:
| The api is anything but small.
| j-krieger wrote:
| React features 13 top level functions and 11 hooks. That
| remains an extremely small API for a frontend framework.
| epolanski wrote:
| It's a library, not a framework.
|
| Add a router like react-router and you have another 20
| apis.
|
| Add on top of that a state manager, even small ones, and
| you're adding another 10/15 apis.
| chatmasta wrote:
| That's irrelevant to your original claim that React is
| not a small API. btw, have you seen the DOM API? It's
| huge!
| christophilus wrote:
| It's pretty small compared to most UI frameworks I've seen.
| JoeyJoJoJr wrote:
| Well, what compatible library would you consider small?
| ojkelly wrote:
| > Unbelievable that they've gone ahead launching this
|
| I hope the irony of criticising a team for launching something
| early, on HN _of all places_ isn't lost on you.
|
| > going all in on hooks
|
| They went all in on hooks in 2018 when they rewrote the
| internals with React Fiber.
|
| Hooks are how react works, class components are more of an
| abstraction--not less.
|
| > while the fundamental problem with them, which was raised in
| 2018 is still unsolved
|
| If it was a showstopper it would have been fixed by now.
| spencerchubb wrote:
| I think you're a few years too late to criticize for going all
| in on hooks. Sure, there may be deep rooted problems, but
| there's a lot of inertia.
| klysm wrote:
| It's odd that sooo many things are still successfully built on
| top of react.
| whakim wrote:
| This is certainly an issue/annoyance (along with other things I
| don't care for about React), but calling it a "fundamental
| problem" and "embarrassing" ignores the vast, vast majority of
| React users who manage just fine.
| hummus_bae wrote:
| This may come across as naive, but could you expand on the
| significance of this issue for people who don't use React every
| day? I see that lots of people think this way about Hooks, so
| I'm honestly just curious about what React users think is such
| a big deal
| abxytg wrote:
| its not naive. this isn't a problem you're likely to run into
| or have to work around. It is a thing that pedantic people
| bring up to justify the trouble they have keeping up with the
| pace of change in front end dev.
| abxytg wrote:
| Can you elaborate on what this issue prevents you from doing? I
| write production react code that is used in medical devices
| every single day and I have never had this problem stop me from
| developing a particular screen or piece of functionality, and I
| use pretty much every niche edge web API that there is.
|
| Hooks has made me 3-4x more productive. If a technicality is
| stopping you from enjoying it, that is such a shame.
| martpie wrote:
| How is that an actual _fundamental_ problem?
|
| The world has embraced hooks, for better or worse. The fact is
| React still works well, and the React team has always been
| clear that performance is (somewhat) an implementation details.
| For example, they often advertise to use inlined functions and
| to use `useCallback` only if you're facing performance issues.
|
| So `useCallback` invalidation is definitely not "fundamental"
| (imho)
| wetpaws wrote:
| JS world has a long running tradition of embracing things
| that in retrospect they should've not.
| ajkjk wrote:
| What are you talking about? Hooks are fine and are out there
| working fine for everybody. They have some rough edges but it's
| not, like, some catastrophe.
| aidos wrote:
| I've not read through the thread but I wonder how much of it is
| effective replaced by the upcoming useEvent hook
|
| https://github.com/reactjs/rfcs/blob/useevent/text/0000-usee...
| nayroclade wrote:
| It might have, but that RFC has been withdrawn.
| danabramov wrote:
| The quick version is we're looking at this from two
| different sides:
|
| - To avoid re-triggering stuff from Effects, we _are_
| adding a Hook. It has the same API as the original
| `useEvent` proposal but is more tightly scoped to this
| particular use case (and different semantics). We'll submit
| a new RFC for it after some more testing, but it's
| available (as `useEffectEvent`) in experimental builds, and
| the docs mention it: https://react.dev/learn/separating-
| events-from-effects#decla...
|
| - To improve rendering performance, we are working on an
| automatic compiler that analyzes your code and makes
| rendering much more granular. It's still in active R&D but
| we hope to share an update on it soon.
|
| We think these two things together will likely be able to
| mostly address the issue. If not, we'll look at the
| specific gaps and work on them more closely.
|
| In general though, people have shipped huge apps with
| Hooks, and it's definitely production-ready. Always an
| opportunity for improvement, sure.
| febusravenga wrote:
| I'm having hard time understanding why `useEffectEvent`
| is so limited.
|
| > * Only call them from inside Effects.
|
| > * Never pass them to other components or Hooks.
|
| (https://react.dev/learn/separating-events-from-
| effects#limit...)
|
| The original proposal was more about `events` this one is
| about effects.
|
| According to these rules, i can't do
| const x = useEffectEvent((event) => console.log("abc"))
| return <MyCustmButton onClick={x}/>
|
| Why isn't it allowed?
| Rapzid wrote:
| TBH I can't even figure out what useEffectEvent does
| after reading the docs and looking at just about every
| Google hit for it. Please let me know if you figure it
| out.
| Rapzid wrote:
| OT but if I never see connection handling and connection
| callbacks mixed in with React components and stale state
| refs in a real, production app I'm responsible for..
| It'll be too soon.
|
| Alas, since it's being "promoted" in the React doc
| examples I'm guessing I haven't seen the last of this :|
|
| On-topic: I read all that and have no clue what
| useEffectEvent does. Why can't I just use a closure?
| Passing the effect event is listed as a limitation, but
| it's never explained why it can't be passed. What
| happens?
| nayroclade wrote:
| Yeah, I've helped build some of those huge apps, and I've
| ran in these issues and wasted countless hours debugging
| and working around them in all of them.
|
| And what do we get from the React team? After five years?
| More vague promises. More RFCs. More blog posts. More
| tweets. More docs mentioning nonexistent APIs. No actual
| shipped solutions. Forgive me, but I just don't believe
| you anymore at this point. Five years.
| kristiandupont wrote:
| What an incredibly entitled attitude.
| aidos wrote:
| I mean, with that attitude?
|
| You're obviously a bit frustrated but as someone who has
| done a lot of React over the years I don't quite get what
| you're running into that would make you that upset.
| danabramov wrote:
| Can you be a bit more specific about which issues you've
| ran into? That would help me know whether we're
| addressing them or not. (The linked issue is very broad
| so it's not super clear which part of it you're referring
| to. We think it conflates a few unrelated things.)
|
| I think it's fair criticism we've been slow on shipping
| this Hook. We try to take a very cautious approach to
| introducing new APIs, so we are currently testing it in
| our internal codebase. Once we feel confident the
| approach makes sense, we will make a stable release with
| it.
| aidos wrote:
| Thanks for the update.
|
| There's always a lot of complaining about hooks but
| honestly I think they're generally pretty wonderful.
| Occasionally you need to do some gymnastics but more
| recently I've lent on the useEvent pattern to detach
| reactive and non-reactive code and it's working nicely.
|
| Is there something I should know about useEffectEvent vs
| useEvent? We use the pretend / poly fill version and I
| understand it behaves slightly differently. But in
| general we just want a function that doesn't change that
| always calls the latest version of the real function.
| Mostly we're passing it down to other components that use
| it as an event handler or sometimes in a useEffect
| themselves.
|
| As ever, thanks for the work on React.
| danabramov wrote:
| _> Is there something I should know about useEffectEvent
| vs useEvent?_
|
| Yea. It still proxies to the latest version, but it
| doesn't give you a stable function. (In fact, it always
| gives you a new one in DEV to avoid depending on its
| identity.) Instead, the _linter_ lets you (actually,
| forces you) to omit it from dependencies. Conceptually,
| it's a non-reactive piece of code. There's also a new
| limitation that you're supposed to only call it but not
| pass around (also enforced by the linter). There's a
| bunch of reasons for this design which we'll write up in
| the RFC. (TLDR: you only really know whether something
| should be reactive or not next to the actual callsite.)
| aidos wrote:
| Sounds like that's probably ok in practice - you can use
| it nearer to the location of the useEffect.
|
| Though, in our case we use mobx so a lot of our
| components are effectively memoised on shallow prop
| comparison. Here the ergonomics of stable function
| identity work well at a higher level in the stack. You
| can avoid rerendering large parts of the tree if your
| event handlers are stable.
|
| I'm a little worried that the api you describe will work
| against us here (and I'm also generally a little
| concerned that the smarter compiler stuff you guys are
| working on might not play as nice with a mobx world - but
| maybe that's not true).
| danabramov wrote:
| We can only play very well with the stuff that works by
| the React rules. It's the only direction that it makes
| sense go into, IMO -- we are exploring a particular
| paradigm, and we might as well squeeze everything we can
| out of it. So to reap its benefits we also need to work
| within its model. We do have escape hatches for the other
| stuff but this is exactly the reason we're cautious about
| recommending something that is in a different direction
| than our model. At some point we want to rely on some
| property, and if it's not there, it just doesn't work.
| davidatbu wrote:
| I've had to write my own `useCallbackOne()` hook that is
| guaranteed to not be recomputed if it's dependencies don't
| change. export function
| useMemoOne<T>(valueProducer: () => T, deps: unknown[]) {
| const [initialValue] = useState(valueProducer); const
| memoizedValue = useRef(initialValue); const
| memoizedDeps = useRef(deps); if (
| deps.length != memoizedDeps.current!.length ||
| _.zip(deps, memoizedDeps.current!).some( ([dep,
| memoizedDep]) => dep != memoizedDep ) ) {
| memoizedValue.current = valueProducer();
| memoizedDeps.current = deps; } return
| memoizedValue.current; } // eslint-
| disable-next-line @typescript-eslint/no-explicit-any
| export function useCallbackOne<T extends (...args: any[]) =>
| unknown>( fn: T, deps: unknown[] )
| { return useMemoOne(() => fn, deps); }
|
| FWIW, for this and other reasons, I've recently been looking
| into "actually reactive" frameworks (like Solid/Svelte), and I
| think I vastly prefer their paradigm to react's.
|
| Specifically, I used sycamore-rs to build a Rust/WASM UI, and
| it's great (once you get the hang of dealing with lifetimes in
| sycamore).
| bmikaili wrote:
| if you like sycamore check out dioxus.
| explodingcamera wrote:
| Looks really nice! Also, super happy that the interactive
| examples are not super sluggish code sandbox iframes, they're
| actually usable! A more typescript-first approach would have been
| nice, or at least typescript/JavaScript toggles, but the React
| team seems to be aware that that's an area they need to work on.
| danabramov wrote:
| Yeah we'd like to add TS throughout but it will require some
| technical and some content work. We didn't want to block the
| release on that.
| johtso wrote:
| The sexiest example I've seen is in the XState docs.. not
| sure what they're using to get the types into the tooltips..
| https://stately.ai/docs/xstate/running-
| machines/react#usemac...
| nawgz wrote:
| Looks like Shiki: https://github.com/shikijs/shiki
|
| If you "inspect" the elements with the mouseovers, you can
| see they statically compiled the TS definition into the
| HTML.
|
| I guess it probably uses the same APIs to read the types
| VSCode does, given what they state the purpose of Shiki is.
| afidrya wrote:
| It's Docusaurus 2 + TwoSlash:
| https://docusaurus.io/blog/2022/08/01/announcing-
| docusaurus-...
| johnny_canuck wrote:
| That is something I really dislike about the react-query docs,
| the examples are code sandboxes. Glad to see they didn't go
| that path here. I find they add a lot of friction when I am
| looking for a quick reference.
| anthonypz wrote:
| I recently went through the entire beta React docs (took me about
| 3 weeks) and was blown away by the quality of the tutorials. The
| live code playgrounds and challenges are amazing. With the recent
| debate about reactivity and which framework implements it best
| (solid vs. react vs. vue vs. svelte), I felt that what mattered
| most to me as a junior dev is the quality of the documentation. I
| gained a strong enough understanding of the complicated concepts
| (dependency arrays and the useEffect hook) because the docs were
| so good. There is always room for improvement in JS land and
| other frameworks are constantly innovating, but the thing I
| always fallback to is: how good is the documentation?
|
| Side note: I recently took an assessment test on React through
| Triplebyte and was given an expert level badge (for what it's
| worth). I think that speaks volumes about the new React docs
| because that is where I gained most of my React related
| knowledge.
| [deleted]
| benrutter wrote:
| Looks like some good resources and a neat redesign. The domain
| move makes me realise how odd it was that before they had 'org',
| which is normally used by charities/non-profits. I'm guessing
| Typescript is the force behind dropping 'js' from out of the
| domain too.
| sophiebits wrote:
| As the person who most often pushed for .org, I can say it was
| because I wanted to emphasize the community nature. React isn't
| a commercial offering. (I had to talk the team out of react.com
| as the main brand for this launch; although that URL works, I
| think react.dev is more reflective than .com of what we're
| trying to do.)
| vbezhenar wrote:
| IMO React is missing hooks to work with promises. I made that
| hook myself but I think that promises along with AbortSignals (to
| interrupt promise if React decided to cancel it) are basic JS API
| and React should just support them out of the box. I saw too much
| code which deals with async functions in useEffect in a buggy
| way. Things like ReactQuery are nice but they should not be
| required.
|
| Here's my implementation, for the record:
| https://pastebin.com/rjj0FDDd
| danabramov wrote:
| We agree. https://github.com/reactjs/rfcs/pull/229
| j-krieger wrote:
| You probably won't answer, but what do you think of the (imo
| uncalled for) wishful thinking that react should've stayed in
| the direction of Class components?
| sophiebits wrote:
| Dan wrote an answer today about classes here:
| https://news.ycombinator.com/item?id=35188669
| subleq wrote:
| react-query basically converts promises to hooks
| idkwhoiam wrote:
| > Here's my implementation, for the record:
| https://pastebin.com/rjj0FDDd
|
| This implementation doesn't account for the fact that the
| promise may settle after the component has been unmounted.
| fireant wrote:
| Missing standard downstream promise cancellation is arguably
| one of the bigger problems in the whole javascript ecosystem.
| In C# almost every async function has a CancellationToken
| parameter, same in Go with Context.
|
| Even after years of writing fullstack javascript this is my
| first time seeing AbortSignals, probably because nobody uses
| them. Some libraries, like Axios, handroll their own
| cancellation mechanisms, but that does not really cut it.
| waboremo wrote:
| Finally! Although looks like Google still has to update so
| newcomers are likely still going to head to the legacy docs and
| not realize it (and the legacy page still links to
| beta.reactjs.org vs react.dev).
|
| A tremendous improvement though, and it must have been a lot of
| work coordinating, especially the easier to digest images
| sprinkled throughout.
|
| At last we can officially move past the era of class components.
| danabramov wrote:
| We'll make the legacy site binner a bit more prominent and
| clear -- thanks for feedback. I planned to but got distracted
| with other things during deployment.
| waboremo wrote:
| Perfectly understandable, it's a huge change and these
| smaller things fly under the radar easily. Congrats to you
| and the team for pulling off the major transition smoothly!
| [deleted]
| chrismsimpson wrote:
| VanillaJS/web standards all the way. I love being able ship
| something knowing exactly what's going to end up in the browser.
| I really don't get the react cargo cult fad, and when it finally
| dies it won't be too soon.
| dmak wrote:
| I don't get how anyone can build a serious application on
| vanilla JS. I love vanilla JS, but it would require one to re-
| invent the wheel to manage all the state. You'll end up
| borrowing tons of ideas and rolling your own framework. At that
| point, you might as well have used something like React,
| Svelte, etc...
| klysm wrote:
| Sounds nice for a solo project.
| chrismsimpson wrote:
| You know react itself is written in something
| klysm wrote:
| Yes that is true, but I'm not sure what you are
| insinuating.
| unmole wrote:
| > react cargo cult fad
|
| React has been around for nearly a decade now.
| JaDogg wrote:
| Since I'm not a real frontend developer. I just use bootstrap +
| jquery. It works fine for personal projects.
| j-krieger wrote:
| React will never die. It's as pervasive than jQuery and has
| been for a while now.
| chrismsimpson wrote:
| "React will never die, just like jQuery". Lol.
| solumunus wrote:
| Plenty to be made contracting legacy jQuery projects.
| recursive wrote:
| I'd settle for the hype levels to reach parity with jQuery.
| ezekg wrote:
| Is there an explanation somewhere on react.dev covering how Hooks
| actually work under the hood? They're the most magical part of
| React, and everybody I know (including me) had a hard time
| actually grasping _how_ they work and _why_ , for example, you
| can't use a hook inside an if branch.
|
| Edit: there are a lot of good--and varied--explanations here.
| Which is why I think the docs should cover it in-depth. It's
| confusing.
| a_humean wrote:
| Basically the way of thinking about is that there is a runtime
| that knows what component is rendering, and your hooks are
| communicating with that global runtime. This is why hook order
| and consistency matters - there is basically something globally
| that identifies a hook by its index order of execution and the
| identity of the component instance that is currently rendering.
|
| So there is a data structure that store says `[useMemo,
| useState, useEffeect]` - and when you component re-renders, is
| unmounting, or has effects to trigger it uses the index order
| to lookup the bit of state that needed to persist.
|
| This is a pretty good high level explainer of how react works
| that touches on some of that: https://overreacted.io/react-as-
| a-ui-runtime/
| yamtaddle wrote:
| I read the code when they added them. It may have changed, but
| here it is:
|
| 1) A hook adds a function or variable to one of several lists
| attached to the component object, when it's instantiated (yes,
| even your "functional" components are objects, and I don't just
| mean in the JS-functions-are-actually-objects sense--at least,
| they were when I read it)
|
| 2) Subsequent calls either call those functions, or
| accesses/modifies the value, in a FIFO manner, reading them out
| of those lists. This is why you can't mess with hook ordering
| in e.g. loops.
|
| It's basically just methods and properties on an object, but
| with FIFO access based on declaration order, instead of using a
| lookup table of some sort.
|
| [EDIT] A poster correctly pointed out (then deleted their post)
| that I wrote "loops" where I meant "conditionals". Technically
| sorta-true (though not quite, as phrased) if the loop isn't the
| same length every time, but yeah, I meant conditionals. Point
| is, the reason order matters is that the whole thing's just a
| bunch of FIFO queues, more or less.
| [deleted]
| orange8 wrote:
| > and why, for example, you can't use a hook inside an if
| branch
|
| Within the component functions's body, you may have many calls
| to the same hook, lets take useState() as an example.
|
| Each useState() returns a different state variable, that is
| kept track of in a cache outside the component function.
|
| On the first render, the state variables are created. On
| subsequent re-renders, the state variables are read from the
| cache.
|
| The cache is a simple array. It keeps track of, and identifies
| each individual state variable from it's index in the cache
| array.
|
| The first call to useState() gets slot 0 in the array, the
| second call gets slot 1 and so on and so forth..
|
| For the tracking to work consistently, all calls to useState()
| within the function's body must also happen consistently.
|
| In the same order, every time. Having a useState call within a
| conditional "if" branch breaks that consistency.
| simonw wrote:
| My high level understanding of how they work is that they
| remember the sequence in which they were called - so if you
| call the same hook three times, those three calls are held in a
| list - and future actions that should retrieve them get access
| to the correct data.
|
| If you were to call them in an "if" branch it would mess up
| that queue mechanism.
| spion wrote:
| 1. They work by setting a global variable to the value of the
| current component then calling the render function. Whenever
| you call a hook you're effectivelly dispatching it to the
| component in question, OOP style.
|
| 2. React counts the number of executions of (certain) hooks.
| This count is how it knows which state to get from the store as
| a return value from `useState`. useState is effectively
| `getStateAndSetter()` but it doesn't pass a key name of any
| kind, so the implicitly passed key is `hookCount++`. This is
| why you can't call hooks conditionally, or state would get all
| messed up - if a condition turns false and one hook doesn't run
| that render, all getStateAndSetter calls that run after it will
| be off by one.
| paganel wrote:
| I know almost nothing about React, let alone React hooks, but
| all this looks a little hack-etty, doesn't it?
|
| Also, I'm curious if there is any similarity between these
| React hooks and the infamous Drupal hooks.
| rizky05 wrote:
| It's different but has similarity. Both are function that
| gets called when some lifecycle is reached.
|
| React hooks is running on each component, not on whole app.
| React app is composed by bunch of components, and each of
| those have their own hooks.
| spion wrote:
| Its absolutely hacketty, yes.
|
| Not familiar with Drupal.
| Matheus28 wrote:
| Here's how I'm pretty sure they work (although I haven't
| actually looked at the internals). Since your `<Tagname
| props>children</Tagname>` gets turned into
| `React.createElement(Tagname, props, children)`, this means
| your `Tagname` function isn't called directly. So before it
| calls that function, it sets up a "context" that the hooks will
| use during that function call (with a global variable pointing
| to that context so the hooks can find it). We could use an
| array with one element for each hook invocation. So each
| useState would use a different slot in that array, etc. This is
| also why the order and number of hooks must always be the same
| for a given function, since their identifier is their index in
| that array.
|
| Additionally, this context would also have the context of
| children elements, so things can actually be persisted across
| function calls and React can know what needs to be mounted &
| unmounted.
|
| Also note that because Tagname isn't called directly, it's also
| how React is able to do its diff and only actually call what is
| needed.
|
| This is also why if you're generating a dynamic number of
| elements (ie outputting an array of elements), you should
| provide a `key` prop, so it can link up the elements to their
| corresponding past states each time the function runs.
| danabramov wrote:
| I find this to be a very nice high-level explanation:
| https://medium.com/@ryardley/react-hooks-not-magic-just-arra...
|
| In reality we use a linked list rather than an array. If you
| wanna dive into the code, I can give some pointers. For
| example, useState is implemented like this during first render
| (https://github.com/facebook/react/blob/87c803d1dad7e5fe88634..
| .) and like this during next renders (https://github.com/facebo
| ok/react/blob/87c803d1dad7e5fe88634...).
|
| However, _conceptually_ I'd recommend to think of Hook return
| values similar to "extra inputs" to your function, kind of like
| extra arguments. There are different ways to formalize it in
| different languages. We picked plain function calls for
| simplicity and low overhead, although you could imagine `yield`
| with generators or something like that.
| imbnwa wrote:
| >In reality we use a linked list rather than an array
|
| Why a LinkedList rather than an array?
| acemarke wrote:
| The simplest version is:
|
| - React has a module-scoped variable in the hooks
| implementation file that tracks which component is currently
| rendering
|
| - The internal "Fiber" data structure that describes a
| component instance has a linked list of hook contents (saved
| values and callbacks)
|
| - As each hook gets called, React tracks the current hook
| entry, looks up the current hook data, and returns it
|
| So, the number of hooks used needs to be the same each time the
| component renders so that the linked list entries match up
| consistently.
|
| There's a great talk by @swyx here that builds a miniature
| hooks implementation in about 30 minutes:
|
| https://www.swyx.io/hooks
| airstrike wrote:
| _> Believe it or not, React will soon be ten years old. In
| JavaScript years, it's like a whole century!_
|
| Hilarious! As someone who was once a "full-stack" web dev in the
| age of jQuery, CSS resets and local fonts only, this definitely
| rings true.
|
| And having just started learning React (through Next.js), this is
| a timely and welcome refresh! Thank you!
| epolanski wrote:
| React's first implementation (on top of Ocaml) is from 2011 I
| believe.
| njsubedi wrote:
| It's funny how react.com redirects to reactjs.org and that
| redirects to react.dev domain because most companies only use
| newer tlds because dotcoms are unavailable
| funstuff007 wrote:
| > We've included diagrams, illustrations, challenges, and over
| 600 new interactive examples.
|
| 600! It's hard for the competition to keep up with that.
| jmull wrote:
| I can't figure out why anyone chose to use react...
|
| I understand the "it's dominant and has a large ecosystem"
| argument, but I just can't wrap my head around how enough people
| chose it for it to reach this position.
|
| I've evaluated it a couple times and it just looks poorly
| conceived. Fixes and "improvements" have rolled in, but they are
| also poorly conceived and themselves need fixes.
|
| Of course I know it might just be me... I didn't get the point of
| tailwind either, until I used it.
|
| But I've also used react for a reasonable sized project and I
| still don't get it.
| doodlesdev wrote:
| The original API when it was originally released was much
| saner. That was before JavaScript even had "classes" which
| meant React classes didn't have nearly as much boilerplate.
| After they migrated the API for React class components to be
| JavaScript classes it all went downhill. And then the
| functional people came and the rest is history.
| klysm wrote:
| What's your preferred framework? I quite like react with
| hooks - it's the best thing (to me at least) I've used so far
| to make UIs.
| christophilus wrote:
| What don't you like, and what do you prefer? I like having view
| be a function of state (like in traditional web apps, except
| richly interactive).
| jmull wrote:
| It's more of an idea than a library. The idea's good but the
| implementation is awkward and incomplete. You're endlessly
| writing boilerplate and incorporating libraries for even
| basic and typical cases that a more thoughtful design would
| make unnecessary. Even with multiple evolutions the problems
| are only somewhat resolved. The virtual DOM was a bad idea
| from day 1 and remains so. React wants components to be the
| unit of rendering, but an app wants a component to be a unit
| of app UI. These concerns end of conflicting and competing,
| which the dev has to do the heavy lifting to resolve, with
| things like useMemo/Callback. It uses javascript to represent
| HTML (HTML is already the ideal way to represent HTML
| declaratively).
|
| > what do you prefer
|
| Svelte, for the case you mention.
| spion wrote:
| > HTML is already the ideal way to represent HTML
| declaratively
|
| I'm curious what you mean by "declaratively", and I wonder
| why everyone puts so much value into that particular idea.
| What is declarative? Is it different/better than using pure
| functions? Why? If not, why doesn't HTML have (pure)
| functions?
| jmull wrote:
| Declarative just means declaring the result rather than
| specifying how the result is achieved. (It naturally
| implies the existence of something else that can realize
| the declarations. E.g., HTML needs the browser to render
| it.)
|
| Pure functions _are_ declarative. It 's flexible so you
| can push it to the point where it's essentially a
| tortured imperative form, but you're probably doing wrong
| if you get to that point.
|
| The goal of react and other web UI libraries targeting
| browsers and web views is to render HTML, but
| dynamically, based on the immediate application state.
| HTML isn't dynamic and we naturally want to use
| Javascript for the dynamic part (due to history and
| Javascript's great flexibility).
|
| You _can_ use HTML for the HTML and Javascript for the
| dynamic stuff. A lot of things work this way. But react
| decided to use Javascript for both the HTML and the
| dynamic stuff. JSX mitigates this to a degree, but it
| actually represents XML, not HTML. Thus you use className
| instead of class, close <input> tags, etc.
| spion wrote:
| The reason why I don't think HTML is the ideal way to
| represent HTML declaratively is because HTML does not
| have pure functions or any sort of proper first-class
| values.
| meowtimemania wrote:
| React had a small simple API surface, made it super easy to
| create reusable components, and was more performant than some
| of the other dominant solutions (AngularJS)
| explaininjs wrote:
| Are class components really on the down & out? I tried going all
| in on hooks with a complicated app using lots of web workers and
| generally heavy computation and complex logic (a game). It turned
| in to a bit of a mess until I went for a refactor into classes
| and everything became much more clear.
|
| Having a dedicated place to process changes in props and
| setup/teardown logic is just generally nicer than weird
| dependency arrays and returning destructors from effects.
| montroser wrote:
| I have had a similar experience, and feel the same way.
|
| I tried to give it a real shot with hooks, but the marginal
| benefit they bring seems to be far outweighed by the added
| complexity. Add to that the mixing of paradigms with some
| functional components, some class-based, etc and it becomes a
| mess pretty quickly.
| yamtaddle wrote:
| > Are class components really on the down & out
|
| The hook system is the parts of an OO system that React needed
| to be able to keep developing features & optimizations for
| function-based components, rather than telling their users &
| devs that they'd simply have to use classes for some things. It
| exists so they could side-line class components, rather than
| having to become outright reliant on them for some features.
| So, pretty much, yes.
| phphphphp wrote:
| Most React codebases benefit from the simplicity of functional
| components, because they fit into the model most people have of
| websites + web apps. If you're doing anything complex, you're
| in a very small group.
| Klonoar wrote:
| I would argue the inverse: if your project relatively simple
| enough that hooks don't feel messy, then it probably doesn't
| need to be a React app to begin with.
|
| Class components are just (IMO) cleaner, and I find myself
| saddened at the level of disarray most codebases with hooks
| are nowadays. Enough has been written elsewhere about how
| hooks require one to keep more in their head; class
| components have an agreed up layout/structure/etc that is
| _important_ in large codebases.
| Rapzid wrote:
| On a thread a while back there was a Microsoft eng who was
| on a team that looked into trends with bugs.
|
| IIRC They reported that hooks were a common source of
| problems.
|
| Visually they look simple but they hide a lot complex and
| nuanced semantics. Once you start layering and composing it
| becomes hard to reason about when a value updates, when a
| re-renders will occur, and when a value even resolves(it
| may take many re-renders for a value you need to finally
| get set).
| dylan-m wrote:
| The most frustrating part of this is when you run into some
| library that is all in on hooks and insists _you_ use
| hooks, but your project has been using class-based
| components so far. I was having a great time making a game
| prototype with react-three-fiber until some model loading
| code was just like "fuck you, use hooks" and I ended up
| wrapping a bunch of functional components in special ways
| to basically isolate the hooks stuff so I don't have to
| deal with the headache of it all gradually encroaching on
| the rest of my perfectly functioning project. It's
| frustrating because every time I wonder how to make it not
| a mess, the answer is "haha, we lied, they're barely
| supported; class-based components are for losers and you
| should feel bad."
|
| It's just frustrating. Couldn't they have had the decency
| to fork / rename React for all this and leave the old
| branch to die instead of turning the entire space into some
| kind of pedantic war-zone for several years?
| epolanski wrote:
| I hate the word functional components, they aren't functional
| and it's a deprecated wording in react since the introduction
| of hooks.
| Rapzid wrote:
| Did those React team members finally stop using "render
| functions are supposed to be pure" as design arguments?
| epolanski wrote:
| I think that argument moved only to the returned jsx.
| rkeene2 wrote:
| I find class-based components work better for some things,
| mainly that need to manage complicated lifecycles that hooks do
| a pretty bad job of.
| bayesian_horse wrote:
| I recommend useReducer, if you can't use Redux. Yes, it works
| with non-serializable objects (evenrefs if you must).
| shmde wrote:
| From the docs:
|
| We recommend defining components as functions instead of
| classes.
|
| Not dead but they are not recommended anymore.
| [deleted]
| bottlepalm wrote:
| I think generally you should start with functional components,
| try to keep things simple, and use class components as the
| exception and not the rule. My own app is mostly functional
| components, but I did fall back on a class component in a case
| where I needed the lifted state of a function reference to
| remain current across renders.
| danabramov wrote:
| One pattern you might like to try in this kind of code is
| writing your heavy imperative logic in classes (not React class
| components! just normal classes), and then using Hooks very
| lightly to "connect" and "disconnect" things.
|
| See here for some examples of how you can approach writing the
| same code in a few different ways -- maybe one of these styles
| will fit you better: https://react.dev/learn/reusing-logic-
| with-custom-hooks#ther...
| baron816 wrote:
| I created this library that would allow you to put all your
| state logic into classes: https://github.com/baron816/use-
| structure
| jameshart wrote:
| Yes!!
|
| React apps should, in general, contain much less react-
| specific code than they tend to.
| rscrawfo wrote:
| All of the "tanstack" components seems to be going this
| route which I'm really excited about. I tend to really like
| that stack and roll most other things myself.
|
| Should make it easier to switch frameworks in the future if
| the need arises.
| danabramov wrote:
| For what it's worth, we do think there is _also_ a lot of
| value in building a deep vertical integration in tooling
| so that it can take advantage of React 's unique
| features. A little bit about this here:
| https://react.dev/learn/start-a-new-react-
| project#bleeding-e...
| kimar wrote:
| I'm going through this process right now and would love to
| find examples of a larger open-source codebases doing this,
| in case anybody has references.
| leeoniya wrote:
| i've seen advice on the webs for useReducer instead of a lot
| of useState's...which feels a lot closer to the class-
| component this.setState().
|
| is there a good reason not to uniformly rely on useReducer
| everywhere in a codebase?
| Marazan wrote:
| Because you have to write more code. If all you have is a
| single variable that gets updated with no complex logic
| then writing a reducer seems excessively boilerplatey.
| [deleted]
| chatmasta wrote:
| One example of this pattern is Searchkit [0] which performs
| most of its logic inside a singleton Searchkit class which is
| instantiated and passed as a prop to the root React
| component. A bonus is that it's easier to implement bindings
| for Angular, Svelte, etc. since they can rely mostly on the
| class and just need to call the appropriate methods exposed
| on its interface. For example, it looks like Searchkit now
| suggests using InstantSearch (react-instantsearch-dom) [1]
| from Algolia, i.e. an entirely different maintainer, and it
| creates the bindings with a `Client(new SearchKit(...))`
| adapter [2] around the class (see the code on the home page
| at [0]).
|
| There are downsides to this - you do need to think a lot more
| about code architecture before implementing the code, and you
| can get into a really messy/unmaintainable situation if you
| aren't careful. And you'll need to consider what state your
| "singleton" is tied to - is it really one per page, one per
| component, etc? And depending on the answer, the implications
| may be that this pattern isn't a great idea. But for certain
| use cases, it can work well.
|
| The core premise of this pattern is separating business and
| UI logic, which is not exactly a new idea.
|
| [0] https://www.searchkit.co/
|
| [1] https://github.com/algolia/instantsearch
|
| [2] https://github.com/searchkit/searchkit/blob/main/packages
| /se...
| explaininjs wrote:
| Oh wow didn't expect to hear form you! Yes that's what I'm in
| the middle of right now actually to enable online
| multiplayer: everything regarding the game is in a (class-
| based) state machine in pure JS that can run frontend or
| backend and be interacted with via a websocket client (this
| actually helps with a11y too, navigating a board game via
| aria-labels was a pain in the butt), and the UI (still WIP)
| will be far thinner. Perhaps I'll give hooks a try again for
| that.
| silverwind wrote:
| > Are class components really on the down & out
|
| Class components are still the only supported way to create an
| error boundary. Other than that, they are pretty much dead,
| yes.
| Waterluvian wrote:
| Class components, if you want to use typescript, are a
| nightmare in my experience. So much boilerplate.
| gherkinnn wrote:
| Yes, yes they are. Next to every 3rd party library is written
| to only work with hooks. Every tutorial is written using hooks.
| The new docs (finally) but them front and centre.
| rxhernandez wrote:
| > Are class components really on the down & out?
|
| In the popular sense, they've been on the down and out for
| years now.
|
| > It turned in to a bit of a mess until I went for a refactor
| into classes and everything became much more clear.
|
| in my experience, once the logic starts to become complex, you
| need to develop custom hooks so that a given component stays
| readable.
|
| The hooks paradigm is a lot harder once you get past the
| basics, but I wouldn't go back for reasons I could articulate
| if there's any interest.
| exclusiv wrote:
| I like them too but they tend to promote shittier code. The
| codebases I inherit that use classes = clean, easy to follow.
| Ones all in with functions and React hooks = trash.
|
| Obviously using hooks doesn't mean it has to be shitty, I
| think it just brought a lot more wannabe React devs that have
| no experience with architecture or maintainability.
| the_other wrote:
| I joined my current company around the time hooks reached
| peak hype, and whilst the team I joined were refactoring away
| from class components. My previous gig had used classes. My
| current codebase is complex (a video player) but pushed all
| the core logic out to Rx and custom code, rather than going
| deep with hooks and react ecosystem. So I'm still way more
| familiar with classes despite ostensibly working in a hook-y
| codebase.
|
| I hate hooks. The syntax feels nice to type, but the issues
| outweigh the benefits for me. It's way too difficult to
| understand the rendering lifecycle, the state updating, the
| ordering and I also find the reuse abstraction hard to follow
| (although I accept that might be a concentration/attention
| issue on my part). Conversely, it's also way too easy to
| break the purity of the hook callbacks, so hooks can use
| state from contexts you wouldn't expect (more an issue with
| custom hooks if you don't also supply linter tooling to go
| with them).
|
| Why do you prefer them?
| johtso wrote:
| Pull all your business logic out in to XState machines. Keep
| your React components as just dumb renderers.
| Stevvo wrote:
| Until next year when it's decided hooks have gone out of
| fashion and need be replaced with something else, yes.
| sroussey wrote:
| Using react server components these days and don't see much about
| it.
| interstice wrote:
| Is there a hook for an error boundary component yet or is a class
| component still the easiest way?
| sophiebits wrote:
| Not yet! Other improvements have been higher priority so far.
|
| Many people also use the react-error-boundary npm package, and
| some frameworks have their own error boundary APIs (eg:
| https://beta.nextjs.org/docs/routing/error-handling).
| klysm wrote:
| I encourage people to copy what they need out of react-error-
| boundary and tightly integrate it with their stack. It's
| really not bad
| codeptualize wrote:
| Why are so many comments about class components, I thought we
| ended that debate 3 years ago?
|
| Hooks are better because they allow you to reuse component logic,
| impossible with class components. They solve all the issues and
| gotcha's of HOC's.
|
| Don't compare class components with hooks, compare HOC's with
| hooks.
|
| The best way to grow appreciation for hooks is to try wrapping
| many HOC's and deal with conflicting props and "innerRefs".
| People seem to very easily forget the horrors of the old.
|
| Also lets be real, hooks aren't that bad. Yes dependencies arrays
| and useEffect take some getting used to, but I rarely get into
| situations where I actually get into questionable territory. Use
| react-query/swr for fetching, use Zustand (or whatever) for
| state, and you cut out 95% of the problems.
|
| Anyway, the new docs are great, well done, nice work!
| gnaritas99 wrote:
| [dead]
| spankalee wrote:
| Hooks are much worse because they _poorly_ emulate classes.
|
| What you need for components is a stateful container, with an
| initialization phase, a render function that can be called for
| each update, and lifecycle methods that are called at lifecycle
| events.
|
| Classes give you exactly this:
|
| - Constructor for initialization
|
| - Class fields for state
|
| - A method for rendering that can be called multiple times,
| which can reference state
|
| - Lifecycle methods
|
| Classes are simple, standard, and give you everything you need
| for UI components. They were practically invented alongside the
| concept of UI components.
|
| Hooks try to cram all of this into the repeatedly called render
| method and it's just a failure.
|
| - You have to put initialization into callbacks because the
| whole component is called multiple times
|
| - It's difficult to manage object and callback identity across
| renders requiring useCallback() and useState() to fix
|
| - Lifecycle callbacks are put into hook arguments, but they're
| just trying to be methods and end up recreating the lifecycle
| closure every render.
|
| - Hooks have restrictive rules on their usage
|
| - Hooks make a function no longer just a function. It needs to
| be invoked inside a hook context, making it much less portable
| than a constructor
|
| - Hooks hide their state within the hooks system, making them
| much harder to introspect and debug.
|
| Hooks supposedly solve this composition problem and allow
| reusing logic, but that is entirely possible with classes. It's
| just a huge amount of FUD and misinformation to say that you
| can't do composition with objects. All you need is an object
| interface that is similar to the component interface that the
| component delegates to from its lifecycle methods. This is a
| simple and standard pattern to use and implement: it's just a
| single line of code per lifecycle method. And it's easily
| introspectable with a debugger: just follow object references
| to the helper objects.
|
| lit.dev does with with reactive controllers:
| https://lit.dev/docs/composition/controllers/
|
| It's a very simple alternative to custom hooks, and eliminates
| the need for all the builtin hooks.
| oaxacaoaxaca wrote:
| THANK YOU. Very well said. I've been annoyed by hooks since
| they came out and you described my sentiments perfectly.
| lmm wrote:
| Classes with state are a nightmare. You can never tell what
| has changed or where. Having the state in the hook system
| where it's visible to your tools and you can actually see
| what's changed between one render and the next is a huge win.
| gnaritas99 wrote:
| [dead]
| spankalee wrote:
| You can do that with classes too though. We use decorators
| to make class fields reactive and track what changed
| between renders.
| branko_d wrote:
| Most importantly: hooks make functions that look pure
| actually impure.
|
| Before hooks, if you wanted to call a functional React
| component, you could reasonably assume it's pure - it depends
| just on props and nothing else. Only when trying to use a
| class component did you needed to start to worry about it's
| internal state and how the lifecycle influences it.
|
| With hooks, you are never sure until you look into the
| function's implementation!
| mejutoco wrote:
| Exactly! I could not put it better. All the talk about
| side-effects. Hooks make side effects more confusing, not
| less, for the reasons you perfectly explained.
|
| Small rant ahead. Disclaimer: I find React very useful,
| just not this constant churn of approaches.
|
| One solution would be to make all state pass through a
| single point (like Elm or Redux) but some people do not
| like this because it "limits" them. Limiting side-effects
| lowers cognitive load, same as Type systems are usually not
| Turing-complete. Limits can be good.
|
| Same with Context, which is practical because you can write
| things from anywhere. Congratulations, we were concerned
| about side-effects and now we are basically using a global
| variable.
|
| It is like some people talk about side-effects and
| functional programming and they think it involves using map
| and filter and done and they don't think deeper about what
| it means, and see no contradiction in it where it
| contradicts the principles they are promoting.
| wildrhythms wrote:
| All true. I work on a massive React codebase and it is a
| challenge to follow the logic because at any given time
| there could be a dozen effects firing off from a single
| state change. Granted, having the dependency array helps
| follow what's firing off, but when effects kick off other
| effects it gets into a mess. (Probably a sign that we
| should refactor some things) This problem isn't solved by
| class-based components either; years ago when I first
| started working on the codebase I found class-based
| components with gigantic componentDidUpdate() full of
| hard to follow conditionals and setting state. That said,
| hooks makes it easier to refactor problems like this in
| my experience.
| rimunroe wrote:
| > Most importantly: hooks make functions that look pure
| actually impure.
|
| What makes the functions _look_ pure? Functions in
| JavaScript have no guarantees about purity. TypeScript won
| 't let you make such guarantees either, and I think Flow
| won't either. The only way I could imagine something
| _looks_ pure is if you have prior expectations of what a
| function component should be from how they were discussed
| in very old versions of React before APIs like createRef
| existed. The preferred terminology from the core team these
| days is "function components" and has been for a long time.
| I've been using React since 2014 and they stopped talking
| about "stateless functional components" well before hooks
| were announced in 2018.
| robertoandred wrote:
| Sounds like you should stop trying to think of hooks as
| classes. They're not.
| gherkinnn wrote:
| I don't know where your downvotes come from.
|
| It's a different paradigm, and twisting hooks to behave
| like classes clearly doesn't work. I partially blame it on
| React not properly updating their hooks docs in time
| (they're 2.5y late, ffs).
|
| Hooks are the way to go, class components should have died
| a fiery death back in 2018, and at this point any other
| opinion is just wrong.
| KronisLV wrote:
| > Hooks are the way to go, class components should have
| died a fiery death back in 2018, and at this point any
| other opinion is just wrong.
|
| To your snarky comment, I'll raise my own snarky rant
| from a while ago, about hooks leading to render loops
| that are impossible to debug:
| https://blog.kronis.dev/everything%20is%20broken/modern-
| reac...
|
| It's probably not the kind of writing that I'd strive for
| nowadays but the error message not telling me exactly
| where the problem is felt unacceptable and clicking on
| the error source leading me to React code instead of the
| problematic lines in my code felt just unnecessarily
| weird.
|
| I know that hooks are touted as the best way to extract
| reusable bits of code, however when multiple useEffect
| hooks have issues with dependency arrays and start
| causing render loops, clearly something is wrong.
|
| Personally, I acknowledge that class based components are
| an easier mental model for many out there, but are also
| dead due to the direction that React is heading in.
|
| But I would also suggest that the new Vue Composition API
| does hooks better than React and that using Vue with
| Pinia (instead of React with Redux) will overcomplicate
| things way less for developers who just want to get
| things done.
| codeptualize wrote:
| Skimmed over your article. The infinite loop situation is
| not exclusive to hooks and very much exists in classes.
|
| The situation is calling setState from useEffect, which
| triggers a render, triggers the setState, render, etc...
|
| If you setState in componentDidUpdate without any guards
| you will end up with the same loop. I don't remember how
| debugging this worked, but I'm pretty sure it wasn't
| pretty.
|
| As to big messy components: I don't think you can blame
| that on hooks. Hooks make it easier to split all of that
| up so you have isolated well contained chunks of logic
| that are much easier to test, debug, and manage.
|
| Vue; not super familiar but I believe they use reactivity
| right? I think reactivity can be nice, but is also not as
| great as it's made out to be as it gets tricky as soon as
| you need to take control and prevent extra renders etc. A
| lot of it is making diffing and memoization less
| explicit, which can be nice, but also has some tradeoffs.
| codeptualize wrote:
| It's funny that controllers are conceptually not that
| different from hooks just with classes. Question: can
| controllers access everything on the host? As that would
| easily turn into a giant mess. Probably you shouldn't but
| isn't that the same as hooks rules?
|
| Classes have lots of rules and best practices to prevent a
| mess, just like hooks. Also stateful classes are notoriously
| hard to debug as everything can change everything all the
| time.
|
| I think you also should try hooks for a bit. Some of your
| statements about them are incorrect or really not that
| prevalent in normal use, you might be surprised how nice they
| can be. Especially use react-query or swr for fetching and
| something like zustand for state.
| zarzavat wrote:
| Would generator functions help? function*
| Counter(props) { const [state, setState] =
| makeState(0); const incr = () =>
| setState(state.value + 1) while (true) {
| yield <div onclick={incr}>{ state.value }</div> }
| }
| orange8 wrote:
| This kind of reminded me of the module pattern [1] popular
| with ye olde jQuery plugins. Just realized that hooks try to
| emulate what JS does natively, which is keeping track of all
| local variables in a functions calling scope. Meaning that if
| that function returns an object, that Object still has access
| to all the variables declared when that function run.
|
| [1] https://stackoverflow.com/questions/17776940/javascript-
| modu...
| dylanowen wrote:
| 100% this. Reading complex functional components is
| challenging because you're creating the functionality of a
| class with non of the organization.
| codeptualize wrote:
| How do you mean? Imo it's easier to organize as you can
| split up your logic into normal functions and custom hooks
| (which are also just functions).
|
| I also find functions much easier to read as there is no
| "this" and you can simply read them top to bottom for order
| of execution.
| dylanowen wrote:
| So I spent some more time reading through using HOCs in
| React and I think I'll have to give functional components
| more of a try. The specific example I was thinking of is
| https://github.com/graphql/graphiql/blob/50674292c55eadf0
| e61... but this component will probably always be complex
| because of the Codemirror interaction.
| codeptualize wrote:
| Nice! I think you might like it.
|
| Ah yeah, that does take a while to unpack. I think a lot
| of the complexity there is dealing with a non-react
| library and the dynamic import(s). Binding non-react
| libraries can be a bit rough.
|
| I do think it's a good example to show the big advantage
| of hooks, if you look at the use of the hook, super
| clean: https://github.com/graphql/graphiql/blob/50674292c
| 55eadf0e61...
|
| Great way to contain complexity and make usage really
| clean and simple!
| bayesian_horse wrote:
| React functional components are not supposed to be complex.
| It's easier to split FCs up than in Vue for example. Even
| React's class based components discourage splitting
| components by adding more boilerplate.
| spion wrote:
| > impossible with class components
|
| I'm not sure thats really true. In a different world, the react
| constructor functions would have access to `this.useState` and
| `this.useEffect` and then you could extract any logic you like
| by dispatching `yourFunction(this)`. HOC are not the only
| alternative design.
|
| Hooks really push at the boundary of the language and I'm not
| sure they're an optimal path once you actually start dealing
| with state.
| codeptualize wrote:
| Access to this.setState would be horrible, imagine the
| conflicts. You need separate state, and then you sort of have
| hooks again.
| spion wrote:
| see https://news.ycombinator.com/item?id=35192312
| rimunroe wrote:
| > Hooks really push at the boundary of the language and I'm
| not sure they're an optimal path once you actually start
| dealing with state.
|
| How do they push at the boundary? I feel like so many people
| talk about them being magical, but I don't see how they're
| any different than any other effectful function call. Is the
| idea of tracking call order that exotic?
|
| This is a very simplified example of how hooks work under the
| hood: let hookStates = []; let
| currentHookId = 0; let firstRun = true;
| function endRun() { firstRun = false;
| currentHookId = 0; } function
| useState(initialValue) { const hookId =
| currentHookId++; if (firstRun) {
| hookStates[hookId] = initialValue; }
| function setter(nextState) { hookStates[hookId] =
| nextState; } return [hookStates[hookId],
| setter] } let actions; function
| run() { const [a, setA] = useState(1); const
| [b, setB] = useState(2); // this is done
| because we're not setting up event handling // and we
| need some way to trigger external updates actions =
| {setA, setB} endRun(); return a + b; }
| function assert(received, expected) { if (received
| !== expected) { let error = new Error(`Expected
| ${expected}, but received ${received}`); error.name
| = 'AssertionError' throw error; } }
| assert(run(), 3); actions.setA(3);
| assert(run(), 5); actions.setB(5);
| assert(run(), 8); actions.setA(1)
| actions.setB(-1) assert(run(), 0);
|
| Obviously this example doesn't include tracking more than one
| component, but as far as I know hook state gets tracked
| pretty much the same as the state on class component
| instances.
|
| I could understand thinking they're magical if you were under
| the impression you were the one calling the component
| functions rather than React, but I think my impression was
| always that it was still React's job to call the function
| component (otherwise, createElement seems like a waste). They
| _might_ have at one point said that it was okay to do that in
| tests, but I 'm not sure about that, and it would have been
| out the door the moment function components started
| supporting refs.
| spion wrote:
| It really IS weird to reason about.
|
| `useEffect(f, [])` runs on every render, but only installs
| the effect once. The other times its not installed. That
| means standard language facilities such as *closure
| capture* don't quite work as expected unless you pass them
| in that list `[]` too
|
| Its not impossible to get used to it, but thinking in hooks
| is profoundly different than thinking with normal
| javascript.
|
| I think the original design wanted so badly for state to
| fully live outside of React, but unfortunately, the
| information about what components are currently active on
| the screen is very relevant for what the state should be
| doing. As such, I think that approach just doesn't work no
| matter how much we'd like it to work.
| rimunroe wrote:
| I never said they _weren 't_ weird to reason about. Side
| effects _are_ hard to reason about. I was responding to
| the claim that hooks "push the boundaries of the
| language". Closures work exactly the same as they always
| do, but they're also something a lot of people struggle
| with and always have. This is all entirely normal
| JavaScript, but that doesn't mean it's going to be easy
| for people. Class components were _incredibly_ easy to
| introduce subtle bugs in, especially because of the
| abilities to do things like define your own non-
| idempotent constructor or doing things like assigning to
| and reading from instance properties (refs are like this
| too, but I 've seen much jankier code around class
| instances than the--already considerable amount--I've
| seen with refs).
|
| Hooks make you run into those potential bugs head-first,
| and that's always seemed to me like what a large part of
| the "hooks are hard to reason about" complaints stem
| from. The other parts are people who expect functions to
| be invoked in a different way than they are. I don't
| really know what to tell those people beyond asking them
| if they've ever seen code calling a component directly.
| spion wrote:
| > Closures work exactly the same as they always do, but
| they're also something a lot of people struggle with and
| always have.
|
| Its not normal for a render function to run all the time
| but the closures mentioned in it to be completely
| ignored. Thats completely the opposite of how most other
| APIs work in the language. Usually, a (constructor)
| function runs once, and the closures returned by it may
| get run multiple times. Completely ignoring the passed
| closures to hooks in many/most cases is something very
| specific to React.
| rimunroe wrote:
| > Its not normal for a render function to run all the
| time but the closures mentioned in it to be completely
| ignored. Thats completely the opposite of how most other
| APIs work in the language. Usually, a (constructor)
| function runs once, and the closures returned by it may
| get run multiple times.
|
| React function components are not constructor functions
| though, so I don't see how those are relevant. Bringing
| up the expectation that constructors "only run once" in
| the context of how hooks are hard to reason about seems
| strange though, as class component constructor functions
| have to be written in a way where they can potentially
| run multiple times. I think that's been a requirement for
| the entire time React has supported JavaScript classes.
|
| What do you mean by "closures returned by a constructor
| function"? Do you mean the instance and its associated
| methods? If so, yes, running a constructor obviously
| produces one instance[1], which is true in React too. But
| you're never invoking that constructor yourself--and you
| never should have been doing that with React in the first
| place--so why would that matter?
|
| Also, I'm confused, can you point at a comparable API to
| a React function component in the JavaScript language?
|
| [1] well, sort of. Constructors can return any arbitrary
| object, so the following works class Foo
| { constructor(n) { return new
| Number(n); } } let foo = new Foo(1);
| foo instanceof Foo; // false foo instanceof Number;
| // true
| spion wrote:
| > React function components are not constructor functions
| though, so I don't see how those are relevant
|
| I'm giving an example of whats a normal use case of
| closures. Running a single function once that creates
| closures that run zero, one, or multiple times is
| "normal". Running a single function multiple times that
| creates closures that run one time and get ignored all
| other calls of the function is not.
| rimunroe wrote:
| > Running a single function multiple times that creates
| closures that run one time and get ignored all other
| calls of the function is not.
|
| This exactly describes a leading-edge debounce function,
| which I was asked in multiple interviews early in my
| career to implement on a whiteboard. I'll admit that
| "problems people feel like giving to junior devs" isn't a
| _great_ method of measuring whether or not something is
| simple, but I think it is indicative of how widely that
| sort of thing is expected to be understood. It also
| exactly describes any sort of request framework where
| request responses are cached after the first call and the
| result is returned without a network hit in subsequent
| calls.
| pharmakom wrote:
| I guess it's because whilst hooks improve on some aspects, they
| are quite counter intuitive and very easy to use incorrectly. I
| don't think hooks is the final answer to side effects and state
| in react.
| hbrn wrote:
| I remember a while ago, if you were to mention HOC wrapper
| hell in React community, most folks would jump to defend it.
|
| Eventually, React team accepted that it is a problem, and
| presented hooks as a solution. The very same people who would
| defend wrapper hell yesterday, would start crapping on it
| today.
|
| I think you're right that hooks are flawed and not the final
| answer, but the community won't accept it until "React gods"
| say so. It would be quite funny if React team eventually
| decides to go compiler way (a la Svelte) and all the people
| grasping for reasons to hate Svelte would have to change
| their opinions again.
| recursive wrote:
| > Hooks are better because they allow you to reuse component
| logic, impossible with class components
|
| I've heard this said before, but I don't understand. Could you
| give an example of component logic that can't be reused under
| class components?
| codeptualize wrote:
| Sure! It's generally about "stateful logic". Basically logic
| that relies on state and/or the lifecycle methods
| (componentDidMount, componentDidUpdate, etc) as with classes
| those are only available as part of a component.
|
| You can "sort of" reuse component logic with classes, the
| most common way is by using Higher order components (see
| https://legacy.reactjs.org/docs/higher-order-
| components.html).
|
| The example in that article is pretty good: Subscribing to
| some external data source. That requires on mount, state, and
| on unmount.
|
| Using HOC's is not actually reusing logic though, it's
| creating more components and wrapping them to compose the
| logic. It's a workaround.
|
| HOC's have a bunch of downsides, imo the most obvious one is
| the props; you need to pass the previous props, and merge in
| the new ones. That can create conflicts. Another typical one
| is refs. You need to be very meticulous about structure and
| how you compose and order your HOC's to make sure it all
| works.
|
| In hooks you can define this stateful logic truly
| disconnected from a component, resolving a lot of the issues
| of HOC's as you can just call a bunch of functions without
| impacting the render tree. The "plumbing" is much simpler.
|
| Hope that is sort of clear, but let me know if I should
| clarify any of this.
| recursive wrote:
| I appreciate the effort, but it's a bit over my head with
| respect to react stuff.
|
| For instance, I'm not sure what's meant by needing to merge
| props. I was under the impression that you could pass a
| subset of properties as an argument to setState, and all
| else would remain untouched.
|
| I wasn't thinking of using HOC's. I've done a bit of react,
| but never touched them. I'm just thinking of reusing logic
| using the same techniques I use to reuse logic in code.
| React famously asserts "it's just javascript". Javascript
| provides a way of reusing logic, namely functions. If I
| have two class components that have the same logic in them,
| I'm imagining just putting that code in a function. This is
| not a sophisticated argument. There might be some reason
| that wouldn't work, but I don't know what it is.
| codeptualize wrote:
| With merge props I mean passing down the local state to
| the next component. If you see the react article I linked
| it's the injectedProps.
|
| I think this might be quite common, if you haven't
| experienced HOC hell I can understand the confusion why
| hooks are necessary.
|
| In terms of putting it in a function: there is only one
| state object per component, you could pass setState
| around, but you can imagine what would happen if many
| functions call it. It's also a lot more effort on the
| implementation as you would have to basically pass state,
| and call do some sort of update in the lifecycle methods.
| It would probably work for one function, but with many it
| will get problematic. You would almost have to write your
| own pseudo hooks framework to make this work in a decent
| way.
| orange8 wrote:
| > React famously asserts "it's just javascript".
|
| I think that specifically deals with when using JSX,
| compared to other templating systems.
| bayesian_horse wrote:
| You shouldn't pass properties to setState. That's a very
| non-reactive kind of thing. Just use the properties
| directly. They should be immutable.
| recursive wrote:
| I confused state and props. The distinction between the
| two has always been a bit hazy to me. I'm not sure what
| "non-reactive" means.
| branko_d wrote:
| > HOC's have a bunch of downsides, imo the most obvious one
| is the props; you need to pass the previous props, and
| merge in the new ones.
|
| Render props (aka. "function as children") are much more
| free form than HOCs - they allow you to "compose the props"
| at the site of usage, as opposed to the component
| implementation.
|
| I don't think there is a use case that HOC covers that
| cannot be done with render props - please correct me if I'm
| wrong.
| codeptualize wrote:
| You are not wrong, I think renderprops are valid, and I
| still use them in some situations.
|
| They are imo not ideal as they are hard to memoize
| because of the render function. It's funny that if you
| try to memoize renderprop components you likely have to
| use some sort of inputs array just like hooks.
|
| Besides the memoization issue it also gets pretty messy
| if you need to implement many of them. Instead of just
| putting things in variables you are now nesting many
| levels deep.
|
| I think renderprops and hooks are functionally not that
| different, but hooks have better ergonomics when using
| many.
| idreyn wrote:
| I have a hook that I copy around between projects called
| `useViewport()`. All it does is watch the current viewport
| size and updates its value when that changes. Because it's a
| hook, I can call this function from any component body:
| const { width, height} = useViewport(); return
| <div>Viewport: {width} {height}</div>
|
| Zooming in, this is just built from a useEffect() to bind
| event listeners, and and a useState() to hold the current
| value. Zooming out, it would be easy to write a
| useBreakpoint() hook that mostly just calls useViewport().
| Hooks compose.
|
| Before hooks, there weren't great patterns for isolating
| units of stateful logic from the presentational side of
| React. A really common pattern was to use "render props"
| where a component keeps some internal state and passes it
| into a function-as-child: <ViewportWatcher>
| {({ width, height}) => <div>Viewport: {width} {height}</div>}
| </ViewportWatcher>
|
| You'd see these provider-components nested three or four
| layers deep, and it got ugly. Hooks solved this.
| recursive wrote:
| I'm not a react expert, obviously, but what would be wrong
| with this? class MyComponent {
| constructor() { watchViewPort((x, y) => {
| this.something += x + y; }); }
| render() { /* ... */ } }
| watchViewPort(callback) {
| addEventListener("resize", (event) => { //
| get x and y callback(x, y); });
| }
|
| This is obviously not production code, and I haven't tried
| it, so maybe something doesn't work? What is this missing
| that hooks provide?
| SebastianKra wrote:
| This is actually a perfect example for why classes are
| insufficient.
|
| You've forgotten the teardown logic. If the user
| navigates from & to this component often. You'll add more
| and more listeners. over time.
|
| The solution would be to store the teardown logic
| somewhere in a class field and then call it from a
| destructor.
|
| Now this unit of logic is in three different places of
| the class. If you need to integrate multiple units, they
| interleave and the class becomes convoluted. Also it's
| easy to forget about the teardown.
|
| Hooks can achieve this lifecycle awareness by default.
| They aren't the only solution though: Vues' refs and
| Sveltes' stores achieve similar results.
| idreyn wrote:
| Hooks let you colocate logic that, in class components,
| would need to be split across multiple lifecycle methods.
| In practice you need to remove the event listener when
| the component unmounts. You can get reasonably close to a
| hooksy API for doing this here: class
| MyComponent { componentWillMount() {
| this.stopWatchingViewport = watchViewPort((x, y) => {
| this.setState({ something: x + y }); });
| } componentWillUnmount() {
| this.stopWatchingViewport(); } }
| watchViewPort(callback) { const onResize =
| (event) => { // get x and y
| callback(x, y); };
| addEventListener("resize", onResize); return
| () => removeEventListener("resize", onResize); }
|
| But being able to slice up logic by functionality, rather
| than by lifecycle event, gets gradually nicer as you have
| more of it.
| theteapot wrote:
| > Hooks let you colocate logic that, in class components,
| would need to be split across multiple lifecycle methods.
|
| I think the obvious OO alternative to hooks would have
| been this: class MyComponent {
| constructor() { this.attachBehaviour(new
| MyBehaviour(this));
| this.attachBehaviour(new MyOtherBehaviour(this));
| } render() { /* ... */ } }
| class MyBehaviour implements ComponentLifeCycleHooks {
| componentDidMount() { /* ... */ }
| componentWillUnmount() { /* ... */ }
| componentDidUpdate() { /* ... */ } }
|
| Weird React didn't even seem to consider when they went
| to hooks. Would be possible to implement yourself though.
|
| I'm not saying this is better than hooks / "composable" /
| "functional" API (I quite like Vue's composable API) but
| it's less of a departure from class based components.
| mattgperry wrote:
| Interesting you assume they didn't consider this. They
| probably did.
|
| How do this two behaviours compose together/interact with
| each other?
| theteapot wrote:
| I made no such assumption. I've just never seen it
| discussed, where as, for example, I've seen "mixins"
| discussed and dismissed (justifiably) as an alt.
|
| > How do this two behaviours compose together/interact
| with each other?
|
| What?
| codeptualize wrote:
| Departure from class based components was one of the
| motivations behind hooks, those are:
|
| 1. It's hard to reuse stateful logic between components
|
| 2. Complex components become hard to understand
|
| 3. Classes confuse both people and machines
|
| See https://legacy.reactjs.org/docs/hooks-
| intro.html#motivation for details. Agree or not, but it
| is a very intentional and well motivated direction.
| spion wrote:
| Thats purely a React API limitation.
|
| The hook API could be class based: class
| ViewportHook { // API on use
| constructor(component) { this.viewportState =
| component.addState(this, initialValue) const
| unsubscribe = watchViewport((x, y) =>
| this.viewportState.set({something: x + y}))
| component.addOnUnmount(unsubscribe); //
| you can also use another hook - hook composition works
| this.otherHook = component.use(SubHook); // use
| the other hook's api } // API to
| expose (in render) value() { return
| this.viewportState.get() // use this.otherHook
| too if you like } }
|
| You would be able to use it in a component like this
| class MyComponent constructor() {
| this.viewport = this.use(ViewportHook); }
| render() { const viewportSize =
| this.viewport.value(); // use in render
| } }
|
| Boring, and a bit less weird.
| orangepanda wrote:
| How would passing a value from one hook to another look
| like, for example, Subhook requiring viewport value to
| set up some subscription?
| spion wrote:
| Good question. component.use(SubHook,
| param)
|
| could be used, that would pass the param as a second
| argument to the constructor.
|
| The main reason why this isn't the case, I think, is
| concurrent mode. Hooks force certain values to be
| retreived and stay stable during render (i.e. you can
| only get a component state value during render function)
| and this is important if there are multiple setup and
| teardowns going on.
|
| (Concurrent mode is IMO a bit of unfortunate React
| complexity that a lot of users of React don't really
| need, and many others can avoid)
| rimunroe wrote:
| This is a hook version of the same code as near as I
| could guess it. function
| useViewport(initialValue) { const [state,
| setState] = useState(initialValue); useEffect(()
| => { return watchViewport((x, y) => setState(x
| + y)) }, []) return state.get(); }
| // usage function MyComponent() {
| const viewportSize = useViewport() // use in
| render }
|
| I made a couple of assumptions here. From usage, I assume
| watchViewport is supposed to both subscribe and return a
| teardown function. I also assume that the
| viewportState.set/get are functions for getting and
| setting the tracked value in the component's state.
|
| In my opinion, there are many advantages to the hook
| version and several major disadvantages to the class
| version:
|
| 1. There's no need for hooks to have a value method or
| React.Components to grow the use or addState methods
| because the hook is just a function call which returns a
| value. How it produces that value is up to the code
| inside the function--which does call out to React--but
| the fact the function will always be called when
| MyComponent is called (absent something throwing earlier
| in the function body of course). The value you see being
| returned by the hook will always match the value you get
| when you call useViewport() in your component. These two
| things are _guaranteed to have the exact same behavior as
| any other JavaScript function call_ and thus you can
| reason about the "registration" and value passing
| without needing to learn any framework-specific APIs.
|
| 2. There's no need for an addOnUnmount method on the
| component object passed to the ViewportHook constructor,
| because the hook function can use the function
| component's equivalent to componentWillUnmount (the
| return value of a useEffect) in the exact same way as a
| function component can, but without need for external
| registration.
|
| 3. In order to implement the class API, you'd need to
| either (A) pass the component's actual instance to the
| hook, or (B) create a new type of value to represent the
| instance of the component the hook is registering
| against. Option (B) is yet another API to learn, as you
| have to learn a new type of object to deal with in a
| React application. Option (A) would mean figuring out a
| way to prevent people from calling those methods after
| construction, OR introducing the possibility of
| registering a new slice of state partway through. The
| latter might be possible, and maybe that's even what you
| intend, but I'd want to know what the expected impact on
| methods like shouldComponentUpdate or
| getDerivedStateFromProps would be. Speaking of those...
|
| 4. I can't think of any obvious way you could pass
| previous versions of hook-related instance properties to
| lifecycle methods in the same way that you can pass
| prevProps and prevState.
|
| 5. Concision: the hook version has a dramatic reduction
| in the amount of code you have to read
|
| 6. Bundle size: because the hook version relies on
| functions rather than class properties, it can be
| minified trivially and thus reduce bundle size even more
| than the obvious reduction in character count would imply
| mind-blight wrote:
| I think the disconnect is reusability. You should not use
| inheritance class-based react components. Therefore, if
| you wanted this logic in another component, you either
| need to copy/paste it or use an HOC. Other commenters
| have shown why HOCs are a pain, so I won't give into it
| there.
|
| Copy/paste gets even worse when you fix the bugs in your
| code: - use `setState` rather than update a prop - handle
| remove event listener on dismount
|
| That extra code makes copy/paste even worse, so HOCs
| become tbe better option. Hooks are even better since
| they don't require passing callbacks into a component to
| get the data
| mejutoco wrote:
| You are also copy-pasting the hook line
|
| > const { width, height} = useViewport();
|
| This could be a library call from a component, using
| normal language constructs. In some languages it would be
| a service.
|
| React is great, but I wished they stopped changing things
| every week.
| codeptualize wrote:
| Every week? Hooks are from 4 years ago..
|
| Only new things now are suspense and server components,
| both completely optional.
|
| React is amazingly stable and largely backward compatible
| (where it's not there are usually codemods available to
| do most of the work).
| mejutoco wrote:
| Context is also relatively new, and capturing errors I
| believe was only possible with class components, or it
| changed recently.
|
| Redux, mobx, etc also were all options to fix the basic
| state management in React.
|
| I concede it is not every week. I should have said the
| preferred approach changes too often for my taste.
| codeptualize wrote:
| I believe context predate hooks. You are right about
| error boundaries, probably should be revisited.
|
| This might be controversial but imo the lack of state
| management in React is a pro not a con. It means the
| community can innovate instead of being stuck with
| whatever the framework provides as is standard with most
| other frameworks. A lean focussed but flexible API.
|
| You can choose the flavor that works for your, patterns
| like React Query, SWR, Zustand, the Atom based stuff,
| it's all a big #win imo. I like having options.
|
| Also I'd say changes in preferences are not exclusive to
| React. React did make the hook change (while still
| supporting the old!), but otherwise the preferred
| approaches are not per se exclusive to React.
|
| I would add that there is nothing wrong with sticking to
| what you are using atm. You don't have to use the shiny
| new thing if the old works well!
| mikeryan wrote:
| Take a look at Use hooks libraries for examples of code that
| you may want to have portability with (this is they
| typescript one because its the one I've used)
|
| One of the simplest examples is "useToggle" which just sets a
| state variable to true or false. Not hard to write in a class
| component but it's still stuff that you may end up writing a
| lot.
|
| A lot of similar ones are click and event handlers that need
| to be cleaned up after the component is unmounted.
|
| useIsMounted is one I use a lot too to ensure I'm not trying
| to write state on an API callback once a component is
| unmounted.
|
| You could add each of these to a class with an hoc and end up
| with
| withToggle(withIsMounted(withUseMediaEvent(MyComponent))) but
| that tends to be a bit of a mess.
|
| https://usehooks-ts.com/
| robertoandred wrote:
| Because any time anything related to React or frontend
| engineering is posted, haters with superiority complexes all
| come out of the woodwork. It's like clockwork.
| rglover wrote:
| Oh, weary traveler, if yer tired of your APIs a changin' join us
| o'er at the Joystick [1] and enjoy a stable sea like y've never
| seen bafore.
|
| [1] https://github.com/cheatcode/joystick
| ddaletski wrote:
| I'm always wondering, why it took web devs so many years to
| create some meaningful reusable UI components (and I still don't
| see a wide adoption of something like that)? I just can't
| understand how reimplementing even such things as simple buttons
| every time from scratch is productive
| JCharante wrote:
| To be fair the designers keep changing the designs of buttons.
| jve wrote:
| Currently microsoft product line like SharePoint, Dynamics
| (Power Apps), Office, Teams, etc, etc is based on FluentUI
| https://developer.microsoft.com/en-us/fluentui#/ components
| that gives also the developers a close enough solution to
| extend UI within said products.
| lloydatkinson wrote:
| Which itself is React, to be clear.
| [deleted]
| qudat wrote:
| Because there is a lot of creativity involved when you are
| placing pixels on a screen. You'd be surprised by how many
| different ways you can render a button. There is no single
| abstraction that satisfies all business requirements.
| adamzerner wrote:
| I've never understood why React components are considered to be
| pure. The output is not just a function of the props, it's also a
| function of the state (as in `useState`) and context (as in
| `useContext`).
| klysm wrote:
| Agree, but it should be a pure function of its arguments and
| the state
| koito17 wrote:
| One thing I find strange about the new documentation is how
| React.createElement is considered a "legacy API". Doesn't JSX
| transpile into calls to that function anyway?
|
| This worries me a bit because some React wrappers for
| ClojureScript expose macros that essentially compile to
| React.createElement() calls, which are now labelled as a legacy
| API.
|
| It also looks like Class Components are officially deprecated,
| given that the documentation explicitly states they are not
| recommended for use in new code.
| mtone wrote:
| I notice that ReactDOM.render is also deprecated.
|
| In our embedded/plugin component scenario where we are given a
| <div> to load in, it appears we should replace our current
| pattern _ReactDOM.render(React.createElement(..._ with
| _createRoot(_jsx(..._.
| danabramov wrote:
| ReactDOM.render has been deprecated since React 18. If you're
| running React 18 with ReactDOM.render, you should already see
| an error urging you to switch because essentially
| ReactDOM.render works in React 17 mode.
|
| Yeah you want
|
| const root = createRoot(domNode) root.render(<Stuff />)
|
| (or the JSX transform output equivalent)
| mtone wrote:
| We're not on 18 yet but things are clear, thanks!
| danabramov wrote:
| JSX has not been compiling to createElement() for a while. (If
| you have the modern transform enabled.)
|
| We're not removing createElement but I'd recommend to change
| your wrappers to the same compile output that the new JSX
| transform (introduced in 2020) uses:
| https://legacy.reactjs.org/blog/2020/09/22/introducing-
| the-n.... The new JSX compile target will allow us to do a
| bunch of optimizations in the future that createElement()
| can't.
|
| I'll make a note of adding this to the docs.
| iamsanteri wrote:
| After using Vue for a long time, React felt like an unforgiving
| piece of cr*p. As time went on and Vue was getting its
| Composition API while kind of moving in the overall direction of
| React, I decided to try class-based components and didn't like
| them that much (this was a couple of years ago). Recently, I went
| through these new docs and read and applied the stuff I learned,
| and I can say it was a surprisingly nice experience. I just
| needed to get friendly with a composition-ish, functional-ish and
| JSX-ish way of thinking. Alone the thought of HTML-in-JS instead
| of JS-in-HTML made me crazy back then (it still kinda does). But
| when you get the hang of building actual user interfaces instead
| of just websites, it makes a lot of sense. If you're comfortable
| with javascript while daring to take the less-opinionated route
| as opposed to an all-out framework, you'll simply feel the power!
|
| Anyhow... To this day, I still think it's an unforgiving, crazy
| beast of a library for a weekend hobbyist developer like me. But
| I kinda like it now and in big part it's thanks to hooks,
| functional components and these new docs. Good job team, and
| congratulations on finally getting this live!
| epolanski wrote:
| As someone who worked with both, vue 3 is miles ahead imho.
| Scoped css, well working two-ways data binding (now being
| mimicked again with signals after mobx demise) and reactivity,
| easier to get performance out of the box without the hook
| madness.
| MoSattler wrote:
| I never really got why people LOVE two-way binding to the
| point that they add things like mobx to projects. IMHO the
| one way data flow makes things so much easier to reason
| about.
| rk06 wrote:
| In Vue two way data binding, like v-model="var1" is syntax
| sugar for `v-bind="var1" v-on:input="var1 = $event.value"
|
| The difference between this and rreact is less typing,
| easier mental model and less issues (because react calls
| render() multiple times)
| Rapzid wrote:
| Which are also just sugars for creating setter callbacks.
| bayesian_horse wrote:
| You only have issues with render getting called multiple
| times if you use React incorrectly...
| epolanski wrote:
| Two-way data binding trades a slightly more complex and
| less transparent rendering model for more efficient
| rendering. You don't re-render the entire component and
| diff the two components you have to understand changes, you
| simply change the leaf.
|
| I'd say in Vue it rarely causes troubles, in React world it
| leads to few non-obvious edge cases where React's one way
| data flow is indeed easier to reason about (but less
| performant).
| branko_d wrote:
| MobX is fantastic! But you do have to change your
| philosophy quite a bit compared to what you would do in
| vanilla React - namely you need to displace most of your
| state management to the outside of the components.
|
| Once you do that, React becomes purely functional (and
| quite "uni-directional", if that's the right term). Just
| update the state (in an event handler or when a Promise
| resolves after a fetch or another part of the UI finishes)
| and UI auto-magically reflects that on the screen.
|
| Arguably, MobX + React is closer to the React's original
| ideal of `UI = f(state)` than the vanilla React itself.
| machiaweliczny wrote:
| Spitting truth right here. The problem is MobX is little
| too unfamiliar for newbies.
|
| I thought Zustand is kinda simplified clone but seems
| like computed properties don't work super well.
| mrj wrote:
| Agreed! Also, you can use strict mode with mobx and help
| force it to be one-way, it's up to you as a developer.
| IshKebab wrote:
| I haven't used Vue 3 but I have used Vue 2 and React
| extensively. React is _much_ better for anything but tiny
| projects.
|
| It has much better Typescript support, and also it doesn't
| have Vue's spaghetti reactivity system, both of which vastly
| increase the chances of bugs.
|
| I guess you could say they're more similar if you simply
| don't care about bugs at all.
| iamsanteri wrote:
| I think typescript support was a priority aspect to be
| addressed for Vue 3 making it sort of a first-class
| citizen. The whole new composition aspect of it was to
| address large codebases and large-scale applications. So I
| understood that V3 makes all the difference if TS support
| and working on larger project is important for you. In
| fact, I think if you are coming from React and try it out,
| you are highly likely to feel right at home there.
| epolanski wrote:
| Good thing then that I specified Vue 3 and not Vue 2.
|
| Vue 3 has excellent TS support.
| IshKebab wrote:
| It's better but it's still not as good as React.
| lfuller wrote:
| What happened to Mobx? It was my understanding that it's
| still going strong.
| iamsanteri wrote:
| In many ways I do agree with you, but by now all these front-
| end frameworks and libraries, including their server-side
| rendered counterparts (like Nuxt, Next, etc.) just keep
| borrowing things from each other.
|
| Regarding performance, I remember having blocking
| sluggishness with v-model that shouldn't have been there back
| in Vue 2 days.
|
| Also, for example, in Vue 3, my favorite component library
| Buefy (based on Bulma) is no longer available, and I don't
| think any of the other ones have (arguably) come so close and
| extensive to what I want.
|
| Vue 2's transition to Vue 3 (if you want to use the new CLI
| tools and the Composition API) had to, by definition,
| fragment the ecosystem in unpleasant ways no matter how
| carefully and sensibly it was managed by the core teams in
| charge.
|
| You can see that Vue went down slightly in recent developer
| surveys, and I suspect this to be among the main reasons. As
| if Evan himself would be suddenly more focused on his build
| tool Vite as opposed to Vue itself (of course it's just an
| illusion).
|
| But I still love Vue because of their amazing docs, and the
| fact that they let me enter the world of web-development in a
| relatively accessible manner (this may not have been possible
| with React, for me personally). Lack of something like scoped
| styles alone baffles me in React to this day, but it makes
| kinda sense in the ecosystem it's operating in...
| KronisLV wrote:
| > Also, for example, in Vue 3, my favorite component
| library Buefy (based on Bulma) is no longer available, and
| I don't think any of the other ones have (arguably) come so
| close and extensive to what I want.
|
| I had a look at the component libraries that are compatible
| with Vue 3 a while back and concluded that either PrimeVue
| or Quasar are some of the better choices for my web dev
| needs.
|
| Surprisingly, many of the formerly popular options are
| stuck with just Vue 2 support.
| lolinder wrote:
| Vuetify is back now, and I've really been enjoying it for
| a side project.
| [deleted]
| epolanski wrote:
| Oh, nice for reminding me, SSR is also better imho on Vue
| with Nuxt than anything in react world. Next.js has the
| tendency of monkey patching plenty of APIs, even broke
| native fetch when uploading anything bigger than 14 kbs.
| MoSattler wrote:
| Remix is the gold standard of SSR to be honest. I worked
| with both, Nuxt and Next.js, but Remix with is heavy
| usage of web standards just makes the most sense to me.
| Rauchg wrote:
| To clarify: there's no "native" fetch to patch. Both Nuxt
| and Next have been adding it to the runtime to normalize
| it across Node.js versions and environments, and to add
| critical capabilities that the Web standard lacked (like
| being able to read the `set-cookie` header or customize
| `Host`).
|
| Worth noting: we've been enabling SSR for React since
| 2016[1], and some of the largest websites on the internet
| SSR with Next.js: Twitch, Hulu, Nike, and even parts of
| Amazon[2]
|
| [1] https://vercel.com/blog/next
|
| [2] https://twitter.com/rauchg/status/1594779272945627136
| parhamn wrote:
| Mobx demise?
| aarpmcgee wrote:
| mobx demise? Did something happen to mobx?
| danabramov wrote:
| Thank you! Glad to hear it made things click :)
| solumunus wrote:
| Svelte > Vue > React
| iamsanteri wrote:
| Is it possible to add Svelte gradually for simple and small
| parts of a website without a compile step? It surely seems
| amazing and all the rave these days!
|
| Then again, the whole front-end ecosystem is moving at a pace
| I cannot quite follow. Instead, I've been going into the
| direction of traditional monoliths and working through the
| docs of Django and RoR.
|
| There you have a plain "good-old" templating language with
| sprinkles of htmx and alpine where you need it. This along a
| bunch of back-end devs that seem to not want to even touch
| the javascript stuff with a stick. It almost feels refreshing
| though, particularly if you want to build rapid MVPs while
| retaining maximum control of your entire stack and IP. When
| teams grow and you need to support extensive and/or thicker
| clients, I believe this is where bigger front-end libraries
| like you mention truly shine. I'm still counting on us coming
| a full circle and there being a re-emergence of traditional
| monoliths in the future though. But then again, with
| supabases, pocketbases, strapis and other "simpler" backends
| of this world, who knows what'll be happening even in the
| nearest future...
| eoic wrote:
| Interesting, I had an opposite experience. I started out using
| React when using class based components was a way to go then
| stopped for quite some time. Years ago I had to use React for
| something and decided to use the new approach with hooks and it
| was such a painful experience - it was harder to learn and use,
| also I introduced many ridiculous rendering bugs. I still feel
| that component based approach was somewhat easier and more
| straightforward to get into even if more verbose.
| iamsanteri wrote:
| Yes, it can be tricky, and sometimes I too catch myself
| asking, "why is it designed like it is" with regards to
| hooks, I won't lie. But, there is something there that makes
| it attractive to me where it was off-putting before. Alone as
| a complement to more extensive state management libraries, or
| other tools intended for larger scale apps, it serves as a
| nice middle-ground solution. You can build your own bits of
| logic in quite an accessible way now too. In other words, for
| me personally I feel that there is something distinct and
| interesting going on here.
|
| Finally, if you combine it with the fact that it seems to
| hold on as the industry standard for jobs, and being useful
| for native mobile development via React Native, it all comes
| together nicely in my mind. With its huge ecosystem and
| closeness to plain vanilla JS, I guess it just makes me
| simply a bit of a better developer and gives me a new
| perspective on things. That's that.
| bpicolo wrote:
| I also like what it inspired in Vue. At first I thought "oh no
| they're taking what React did and throwing it into Vue". But it
| actually ended up to be a very true-to-Vue variant with just
| some idiom similarities. The new Vue 3 ecosystem with Pinia
| blends together nicely
| DyingAdonis wrote:
| React is a leaky abstraction.
|
| https://twitter.com/clark_gunn/status/1636565797412773888
| FractalHQ wrote:
| As someone who learned web dev with Svelte, it seems so obvious
| to me that React is full of convoluted apis born from tech
| debt, and such a bad DX compared to what is possible today. I
| imagine if I learned React first, it wouldn't be nearly as
| obvious to me how mush worse it is than it should be.
| Vinnl wrote:
| Hmm, I can't find the "Edit this page" link that many Docusarus
| (which I assume this is?) sites often have, and I can't find the
| repo either, so I can't submit a PR, but... There's no RSS feed
| for the blog :(
| sophiebits wrote:
| Not Docusaurus, but the source is here:
|
| https://github.com/reactjs/reactjs.org (currently in the "beta"
| directory)
| Vinnl wrote:
| Thank you! Makes it a bit more work, but maybe I'll look at
| submitting a PR later.
| tomgp wrote:
| Lovely site but it got my hackles up right off the bat ...
|
| > "The library for web and native user interfaces"
|
| _A_ library, it's _a_ library not _the_ library.
| gardenhedge wrote:
| React is awesome. When will there be something like it for CSS? I
| feel like CSS is still a mess.
| christophilus wrote:
| tailwindcss.com
|
| It's been a game changer for me. I can't see myself ever going
| back.
| gardenhedge wrote:
| I tried before and didn't love it. Based on how it has been
| adopted I will have to try again.
| madeofpalk wrote:
| Vanilla Extract is probably worth looking into. I feel like
| it's the best option out there for "CSS but better".
| tracker1 wrote:
| Styled Components is relatively popular and is used in the MUI
| (material-ui) library for react. There's also a number of JSS
| libraries as well.
| blowski wrote:
| What would such a library do?
| epolanski wrote:
| I miss elm-ui
|
| https://github.com/mdgriffith/elm-ui
| lloydatkinson wrote:
| Did you look at CSS-in-JS/TS that is exactly this?
|
| https://styled-components.com/
|
| https://vanilla-extract.style/
| epolanski wrote:
| I used styled and currently vanilla, I'm not following
| the comparison with Elm UI.
| [deleted]
| patientplatypus wrote:
| [flagged]
| sophiebits wrote:
| No.
| foxbee wrote:
| Credit to the React team. The docs prior to this were poor - I
| believe the team admitted this.
|
| From the style of writing, to the style of site, I can tell a lot
| of effort was put into this. Will check out react this weekend -
| it's been a couple of years (we've been using svelte)
| anonyfox wrote:
| I'd love to have a simple way of calling
| ReactDOM.renderToString() on my express server that does block to
| actually wait for API calls so that SSR'ed HTML is populated. I
| am very willing to trade performance against simplicity here.
|
| Besides some explorations for suspense and server components,
| there doesn't seem to be any straightforward solution to that
| problem unfortunately
| alvarlagerlof wrote:
| Maybe you can fetch the with an await and pass it down as a
| prop to the component in renderToString?
| s-xyz wrote:
| Amazing! Love it
| [deleted]
| giraffe_lady wrote:
| I've been using I think the beta version of this recently, it's
| definitely an improvement and makes the react api seem a lot more
| coherent than the old version.
|
| I'm glad they fixed the janky scrolling though that has been
| cracking me up for a while. It's an example of a common
| complaint/pitfall with react and even the official docs were
| plagued by it. As a heavy react user and light react hater I love
| to see that shit lol.
| danabramov wrote:
| Please don't hesitate to report things like janky scrolling to
| the issue tracker
| (https://github.com/reactjs/reactjs.org/issues). We were
| changing things _a lot_ and I 'm sure a bunch of regressions
| could've crept in, so all reports are super helpful.
| matsemann wrote:
| The page you linked here
| https://news.ycombinator.com/item?id=35187407
|
| Is basically useless when scrolling. All I see is a gray
| background, and when I stop the content disappears. Makes it
| hard to quickly skim to the correct section.
| pests wrote:
| I have no trouble on my end scrolling that page.
| matsemann wrote:
| On desktop it works "fine", problem is that the scroll
| gets caught inside every code window on the way down. So
| scroll the page a bit, cursor above an example, scroll
| the example until end, then page keep on scrolling, then
| stuck on a new example etc.
|
| On mobile it just blanks when scrolling.
| benatkin wrote:
| Tell me, if React is so great, why isn't Draft.js blowing
| ProseMirror out of the water? And why aren't difficult parts of
| VSCode written with it?
|
| I think a good example of where React sits is Deno. The devs who
| are working _on_ Deno don 't seem to have much interest in React,
| but they are pushing a React framework, Fresh, to make it popular
| with regular devs. They see the popularity of React and not those
| who are frustrated with it. One thing is how much typical React
| code relies on a build step and a bunch of Provider objects. CSS
| Variables can help make components customizable without having to
| do CSS in JS.
|
| I think Web Components, maybe with Lit or Svelte, are making more
| sense for beginning devs. With those you don't have to worry that
| you might need to work on non-react code sometime.
| tracker1 wrote:
| Draft.js is now archived, and not being maintained. That can be
| for a number of reasons. When React first came out, it was
| several years before it really started to pick up steam. I
| think the Angular shift from v1 to v2 helped out React a lot,
| along with create-react-app scripts.
|
| Deno is its' own beast, that I really appreciate. And Fresh
| isn't really a displacement of React, it's their spin on
| something like Next.js, and in some ways a lot nicer even.
| Still using JSX.
|
| Web Components are pretty neat, and I see a lot of things
| moving towards that direction... I also find Lit, Svelte and
| others interesting. All of that said, popularity doesn't always
| mean best, or align with it. Timing, interest and "good enough"
| account for a lot. I happen to like the React way of doing
| things with function based components. I know a lot of the
| transition logic is PFM'd away, but it's fine for most.
|
| I've also been following Rust, Yew and Tauri... doesn't mean
| I'm ready to completely jump ship. React has definite
| advantages when working on larger projects, the ecosystem and
| popularity are only parts of that. I think React + Redux + MUI
| are a really great combination for building applications
| against. In the end, it really depends on what you are making,
| what you are familiar with and what "feels right." I absolutely
| hate(d) angular 1 and 2+ with a passion... I just don't like
| the feel of it. React + Redux is much closer to how I would
| build simulation logic for training/learning well before React
| existed. And MUI is frankly a great component library.
|
| I still keep an eye on what's out there and what's up and
| coming.
| chatmasta wrote:
| > I think Web Components, maybe with Lit or Svelte, are making
| more sense for beginning dev
|
| Beginner devs want to get a job, so they should probably spend
| their time learning the framework that dominates the ecosystem.
| Lit and Svelte are cool, but I don't think they're a great
| target for a first time web developer. Svelte maybe. But
| definitely not Lit - it's a relatively new library and a moving
| target without a lot of adoption, meaning there is a sparse
| ecosystem to fall back on, and you'll need to fill in a lot of
| gaps yourself (both in terms of libraries for common
| functionality, and docs/stackoverflow answers for telling you
| how to do things). Experienced devs can read the source and
| official docs to figure it out, but newbies need more hand
| holding.
| benatkin wrote:
| > Beginner devs want to get a job
|
| Yeah, that's the point I'm making about Deno.
|
| If Deno's own devs avoid anything similar to React hooks
| except when they're trying to appeal to the beginning devs,
| perhaps it would be smart for beginning devs to try to do as
| the senior devs do, not as they say?
|
| The ecosystem of Lit is the web, which has a lot of great
| stuff like MDN. It lets you simply use what you learn there.
| No redirection, like React's onChange translating into the
| input event.
| tracker1 wrote:
| > ... avoid anything similar to React hooks ...
|
| Really?
|
| https://fresh.deno.dev/docs/getting-started/adding-
| interacti...
| chatmasta wrote:
| > The ecosystem of Lit is the web, which has a lot of great
| stuff like MDN
|
| I agree with this, and I mostly empathize with the purity
| aesthetic that comes with it. But I think in practice, you
| need to do a lot of work for common operations that might
| have entire libraries dedicated to them in React. If you're
| a pro developer obsessed with purism, you probably wouldn't
| use those libraries anyway. But newbies don't have time to
| worry about re-inventing the wheel (or at least, we
| shouldn't encourage them to do that, since it will probably
| be a pretty shitty wheel).
|
| All that said, I absolutely love Deno, and I think we
| should encourage new developers to use it, especially since
| it sidesteps the need for build steps in many cases.
| kayson wrote:
| Why did react (effectively) get rid of class components?
| Conceptually, a component seems better represented by an
| object/class than a procedure/function. And aren't classes just
| really functions under the hood anyways?
| wetpaws wrote:
| The original reasoning was, I kid you not "cause classes are
| too difficult concept to understand".
| pyrolistical wrote:
| The quick answer is Hooks killed class
| epolanski wrote:
| We removed boilerplate for higher complexity. We made the 90%
| cases simpler but overly complicated critical paths.
|
| So many useMemo, useEffect, useCallback madness was trivial
| with basic class component lifecycle.
| yamtaddle wrote:
| > Why did react (effectively) get rid of class components?
|
| Supporting some features for hooks and classes, both, probably
| would have meant having two implementations in some cases, that
| might not _quite_ match up as equivalent. More API surface
| area, more code to test, more combinations and paths to worry
| about.
|
| > And aren't classes just really functions under the hood
| anyways?
|
| Other way around, actually: "functional" components end up
| represented by an object.
| robertoandred wrote:
| > Other way around, actually: "functional" components end up
| represented by an object.
|
| No, they're functions.
| yamtaddle wrote:
| Weren't as of a couple years ago--they're represented by an
| object in the React code. Not the case anymore? I'd be
| surprised if they'd messed with that, it seemed pretty
| fundamental to how it operated--hooks were implemented on
| top of that, for one thing.
| robertoandred wrote:
| Nope, just functions. Hooks are also just functions;
| their "magic" comes from them being called in the same
| order in a component.
| yamtaddle wrote:
| OK, so the core of React changed and they no longer use a
| "functional" component to build a component object, which
| used the be the primary data structure in the state-
| machine-like engine at the heart of react, and to which
| they used to attach the lists that contain a component's
| hooks? That's all changed?
| dbbk wrote:
| I'm really not sure why they're so insistent on phasing them
| out. Have I written one recently? No. But I sure do appreciate
| that they exist for cases where you want fine grained control
| over what's happening.
| danabramov wrote:
| _> Conceptually, a component seems better represented by an
| object/class than a procedure/function._
|
| In other paradigms, it is! Our paradigm is exploring the
| functional take. I agree it's a bit unorthodox but we are very
| intentional about modeling it that way. It really has a bunch
| of powerful properties one might not expect.
|
| _> And aren't classes just really functions under the hood
| anyways?_
|
| The key difference is that in React, UI is a pure projection of
| current data (props/state). You're always supposed to "return"
| the UI. Sure a class is a function, but that function is
| invoked once. Its methods can be called many times, but having
| a pure render() method (like in class-based React) is really a
| class cosplaying as a function. Functions are more honest to
| what React is trying to be.
|
| Relevant part from Seb's Hooks RFC comment (https://github.com/
| reactjs/rfcs/pull/68#issuecomment-4393148...):
|
| _> Classes may seem like the ideal thing to hold state since
| that 's what they're designed for. However, React is more
| written like a declarative function that keeps getting executed
| over and over to simulate it being reactive. Those two things
| have an impedence mismatch and that keeps leaking when we think
| of these as classes._
|
| _> Another issue is that classes in JS merge both methods and
| values on the same namespace. This makes it very hard to make
| optimizations because sometimes methods behave like static
| methods and sometimes behave like values that contain
| functions. The Hooks pattern encourages the use of more
| statically resolvable calls for helper functions._
|
| _> In classes, each method has its own scope. It causes issues
| like us having to reinvent default props so that we can create
| a single shared resolved object across those. You also
| encourage sharing data between those methods using mutable
| fields on the class since the only shared thing is this. This
| is also problematic for concurrency._
|
| _> Another issue is just that the conceptual mental model for
| React is just functions calling other functions recursively.
| There is a lot of value to express it in those terms to help
| build the correct mental model._
|
| For a concrete example of where classes as a model fails us,
| consider useTransition
| (https://react.dev/reference/react/useTransition). It lets you
| start rendering "in background" with a different state value.
| But if you get interrupted, the renders have the current value.
| This highlights that in React, the same piece of state can
| conceptually be thought of having more than a single value
| (kind of like being in parallel worlds). Classes don't model
| that well.
| notpachet wrote:
| > Our paradigm is exploring the functional take.
|
| The operative word there is 'exploring'. In practice, hooks
| are still basically OOP, albeit masquerading as FP. You just
| shuffled the state into a shadowy realm adjacent to the
| component where it's harder for developers to see. I know a
| lot of JS developers are allergic to writing the 'class'
| keyword (even though JS doesn't really have classes in the
| first place), and I guess hooks help them sleep easier at
| night by allowing them to believe that they're writing their
| code in a functional way. But they usually aren't. And I
| think that misdirection is the source of a lot of the
| confusion out there regarding hooks.
|
| "The greatest trick the OOP devil ever pulled was convincing
| the world that state didn't exist"
| danabramov wrote:
| I really don't think React is OOP. There is no misdirection
| here -- it really is a different conceptual model.
|
| Even if we set aside implementation inheritance, class
| hierarchies, and all that jazz that got associated with
| modern OOP, fundamentally classical OOP is message passing.
| React components _don 't_ pass messages to each other in
| that sense. The data flows strictly down. Re-rendering is
| not message passing but conceptually reevaluating a part of
| a lazy continuously reactive function call tree.
|
| It's not about "sleeping easier at night" etc, it's just a
| different model. If you're curious to entertain this idea
| for a bit, I have an article you might enjoy reading:
| https://overreacted.io/react-as-a-ui-runtime/
| ep103 wrote:
| Now that we have new docs that have made it clear that
| class components are basically over, will we be getting a
| new version of roadToReact?
| kayson wrote:
| > It really has a bunch of powerful properties one might not
| expect.
|
| Can you elaborate on this?
|
| > a class is a function, but that function is invoked once.
| Its methods can be called many times, but having a pure
| render() method (like in class-based React) is really a class
| cosplaying as a function. Functions are more honest to what
| React is trying to be
|
| useState() is a function cosplaying as a class ;) and that's
| really my biggest hangup. It seems like react components are
| not quite functions nor are they classes but rather somewhere
| in between... And because of JS quirks and perhaps the
| internal architecture/mental model, functions end up being a
| better choice.
|
| > in React, the same piece of state can conceptually be
| thought of having more than a single value (kind of like
| being in parallel worlds). Classes don't model that well
|
| Maybe I'm missing something but this seems like a false
| dichotomy because the equivalent in the class-based model
| would be the render function, not the class itself. And in
| that sense, your set of render functions can also have
| multiple values given a state. Though just writing this out
| does make functions feel a bit simpler.
|
| Admittedly, you've mostly convinced me! And after reading
| through the new documentation, going function-only feels a
| lot cleaner than it did when I learned react using the old
| docs.
| liendolucas wrote:
| I was relatively happy with the React class model, for me it was
| very clear just to override any required methods in a class.
|
| To this day if I need to do something in React I can pick it up
| quickly because is a very simple model: it follows the template
| design pattern, which is one of the most powerful and dumb design
| patterns (I'm talking obviously about the class model).
|
| What's my current issue with React? Well in the same way that
| they have decided to go with hooks and all that, nothing is
| preventing those folks tomorrow to wake up to say: "You know
| what? What we really really need is not functional components but
| a hybrid approach, not fully functional not fully object
| oriented" and then the game starts again.
|
| I worked for a very limited time in one company not long ago, and
| a guy there came and said something like: "We really should start
| using hooks" and I replied: "Really? Why? Can you show me a true
| or concrete advantage using the functional style over the OO
| approach?" then he said: "Well, I don't really need to do that
| just watch this video" and sent me a link of a video (if I recall
| correctly) of the creators explaining all the hooks stuff. I
| didn't even bothered to continue discussing (how can you discuss
| when someone is 100% biased?).
|
| My point is that many people out there just take for granted
| whatever ideas these people are pushing out and not questioning
| things anymore. I'm not saying that hooks are good or bad a thing
| (I really don't know and if I need to learn hooks because that's
| the style used in a codebase, sure I'll do it and probably learn
| something), but blindly embracing things just for nothing is
| harmful.
| codingdave wrote:
| When hooks came out, myself and the other senior devs on our
| team had that same inertia-driven reaction. We knew classes, we
| were comfortable with classes, and they worked. So we asked the
| same question - "Why hooks?"
|
| So we sat down and actually used hooks for a few days -
| refactored small and large components to be sure we understood
| them and saw the difference in the code. We found it to be a
| perspective change -- once we made that change and got used to
| the new syntax, we loved it. Our code was simpler and easier to
| maintain. Once we really learned when to use useEffect so as to
| not abuse it for everything under the sun... the code got
| better still.
|
| So while you are correct that blindly embracing hooks would be
| harmful... Blindly rejecting them is equally harmful.
| willio58 wrote:
| Same experience for my team a couple years back. We hated the
| idea of changing everything to hooks, then we actually
| started using them and fell in love. So much complexity fell
| out of our code we couldn't justify sticking with class
| components.
|
| Having said that, there are some gotchas with hooks that
| aren't trivial and can make them difficult to use/understand
| without significant comments. But hey, what code doesn't fit
| that description?
| ruicaridade wrote:
| To me, the main benefit of react hooks is it eliminates higher-
| order component hell. It's so much easier to extract common
| behaviour from different components to a re-useable hook,
| rather than wrapping a class with a million different higher-
| order components: `withRouter(withFoo(withBar(MyComponent)))`.
___________________________________________________________________
(page generated 2023-03-17 23:03 UTC)