I actually disagree here pretty heavily and think that this doc is due to the bar for competent developers going down in recent years (due to the rise in necessity for more developers of course). There's almost an expectation that powerful tooling should be dumbed down.
The entire doc is written around two common problems:
* You don’t need Effects to transform data for rendering
* You don’t need Effects to handle user events
Both of these problems do not occur if you take the time to understand the tooling React gives you. The events point should be a given, that's just React 101 (and yet they have to spell it out to people...).
You don't end up using useEffect to transform props/state and generate new state if you understand that those things are just variables and you can instantiate new variables using them inside the scope of the component function.
"But that's inefficient because of how re-rendering works".
Great, you understand how re-rendering works but haven't gotten familiar with the useMemo hook. Come back when you've gotten familiar with the primitives available to you in React and how they can all work together in different ways, there's not that many of them!
This doc reads to me like a DIY store publishing an article about how you shouldn't hammer in screws even if it kinda seems like you could if you didn't take the time to understand hammers, screws, and nails. It's sad that it needs to exist but that's the current state of engineering.
Your entire argument here is a shining example of how the growing complexity of react has raised the bar of skill for competence rather than being a victim of lowering the bar.
Think back to the webdev world before react. Was it really that the average dev was more competent, or that the tools of the day were in fact more simple to use? Sure there are more and less efficient ways to use jquery, but unlike react you didn't have to keep so much in your head at once while building a simple feature.
React was designed to be a UI component library. We keeping asking more of it and stuffing more and more complexity into react so that monolithic frameworks can be built with it. It was never designed with that goal in mind and is taking more and more complex features to try to keep that ship afloat.
I really like React. I don't know if this particular pattern was explored before, at least I didn't see it, and I used plenty of UI libraries, from WinAPI, MFC to Java Swing and plenty of web frameworks.
I think that JSX support is a genius thing. Especially with modern TypeScript. I spent so many hours because of string-typed templates that I really value templates integrated within a language.
I really liked original React version with classes. It had its rough edges, but it was simple and accessible to me.
Modern React with functions is not simple. It's so far from simple. I consider myself pretty talented developer. But those hooks - I think last time I had to spend that amount of time is when I learned Scheme continuations. That thing really broke my mind. Well, hooks didn't break my mind, but they just seems to be very easy on the surface yet very hard below surface. I read plenty of articles yet I still don't fully understand them (although I think that at least I can use them without bugs).
For me React is like ORM. It's very powerful tool. I allows to tremendously cut the development time. But it requires absolutely expert knowledge on the team. And it looks so deceptively simple at the same time. This is a bad place for technology to be in.
I first tried react rigtt as it was shifting from class-based to functional components. I actually really liked the functional approach at first, but to me the promise was just pass in props and spit out html. No async components, no hooks, no data fetching, at best it just needs a way to attach even listeners once that fire custom events.
With all business logic outside the render tree it makes a ton of sense and really can be understood extremely fast. Props in, events out. Done. Today everything is a component, and components even have to understand whether they are in the server or browser and how to manage that handoff. It's such a massive dumpster fire of convention-as-a-solution.
Having built a SPA without React it was 100x harder to do it. You had to be careful to update so much state that there was no way really to not break far away stuff when making small local changes. It was a maintenance nightmare.
Yup. And jQuery, awesome as it was, wasn't designed to address the state issue. But it was the best DOM abstraction, so that was the backbone (no pun intended) for many pre-framework applications. It was a spaghetti nightmare.
> We keeping asking more of it and stuffing more and more complexity into react so that monolithic frameworks can be built with it. It was never designed with that goal in mind and is taking more and more complex features to try to keep that ship afloat.
The trouble with a smash-hit library (or, let's be real at this point: framework) is that adding more whizz-bang features to it becomes irresistible, from a résumé-building perspective. Add in that a bunch of the devs are paid very good money to work on it, and they really do have a lot of incentives to keep finding more shit to add to it, rather than calling it "done" and letting it enter maintenance mode.
> It's sad that it needs to exist but that's the current state of engineering.
Wait, wait. I'm trying to make friends with React for less than a month and I do appreciate this article giving me some understanding about the primitives react gives me and when to use it (Or how you called it screws/nails)
I did understand more, but I'm left with a feeling I cannot follow the "flow" of the useEffect as I couldn't understand how can items !== prevItems EVER be true?
// Better: Adjust the state while rendering
const [prevItems, setPrevItems] = useState(items);
if (items !== prevItems) {
setPrevItems(items);
setSelection(null);
}
useState doesn't return immediatelly? Or does it cause immediate re-render? I kind of gathered from the article that all useState calls cause re-render whenever it encounters return.
I am not sure I understand your confusion but here's a few pointers in no particular order:
- the argument passed to useState is initial state, not "forever state". It will seed prevItems for the first render. But later when items prop changes, it's on you to detect the change to what you have as prevItems so far and call setPrevItems yourself.
- items is coming as a prop from outside, prevItems is whatever you set it to last time using setPrevItems
- calling a state setter (setPrevItems / setSelection etc) will always cause a rerender. That's why if you don't have the if condition you have just created an infinite loop - you are inside a render, and if you unconditionally call setX that causes another rerender later etc etc
- that's why I am not a big fan of this particular "Better" example and prefer the later "Best". Avoiding calling state setter function from inside render will make your life easier.
Well, in the first place, this code snippet has nothing to do with useEffect, so I'm not sure why you're bringing it up. They have a separate page that they linked to that explains this pattern in more detail: https://react.dev/reference/react/useState#storing-informati...
But to summarize that page briefly, useState will always return the current value of the state and a function to set it. But "items" here is being used as the default value that's provided the very first time the component is rendered, when the state doesn't exist yet. In subsequent renders, the state exists, so "prevItems" will reflect the last value that was set with `setPrevItem`, not the current value of `items`
yeah I agree with a most of this, but useEffect is still a shit show. It's nasty, and it sits in your code like an anvil, heavy and terse, it even looks like one, with it's lopsided dependency array. The semantics are so strange, and it's not even really for side-effects, more so for synchronizing state. And while I love React, it's not uncommon to see entire codebases where every function is wrapped in useCallback and useMemo, you know, "just in case".
I had a horrible time trying to convince junior devs that they didn't need to memoize everything. Ended up just quitting rather than work with that shit show of a codebase.
Overuse of useEffect is my number one pet peeve for juniors. I can't tell you how many times I have seen a total mess of manual data passing between 3 components with so many if..else cases to handle all the weird stuff.
I catch it in code review and show them that when you delete all of it without useEffects and useStates that it just works. Its an antipattern that turns the code into a giant ticking time bomb if you don't manage all of it out.
> I actually disagree here pretty heavily and think that this doc is due to the bar for competent developers going down in recent years (due to the rise in necessity for more developers of course).
> There's almost an expectation that powerful tooling should be dumbed down.
Which is the problem here. The abstraction in question tries to dumb things down, but doesn't succeed in dumbing things down enough. As a consequence you get their weird middle ground where you can't access the gritty details an experienced programmer would want, but it doesn't hide the gritty details from the inexperienced programmer, ultimately serving no one. As usual, you can make it work, but it is a poor abstraction.
The entire doc is written around two common problems:
* You don’t need Effects to transform data for rendering * You don’t need Effects to handle user events
Both of these problems do not occur if you take the time to understand the tooling React gives you. The events point should be a given, that's just React 101 (and yet they have to spell it out to people...).
You don't end up using useEffect to transform props/state and generate new state if you understand that those things are just variables and you can instantiate new variables using them inside the scope of the component function.
"But that's inefficient because of how re-rendering works".
Great, you understand how re-rendering works but haven't gotten familiar with the useMemo hook. Come back when you've gotten familiar with the primitives available to you in React and how they can all work together in different ways, there's not that many of them!
This doc reads to me like a DIY store publishing an article about how you shouldn't hammer in screws even if it kinda seems like you could if you didn't take the time to understand hammers, screws, and nails. It's sad that it needs to exist but that's the current state of engineering.