For me, trying to make sense of how React's reconciler matches hook invocations to component instances is pure cognitive overhead. Other people don't seem to have this problem. But trying to accomplish anything in React is arduous for me, particularly with function components and hooks. Class components seem a little more obvious.
Usually it just works. But, even following the "Rules of Hooks" (https://reactjs.org/docs/hooks-rules.html), I managed to write some code where the state that belonged to one component ended up in its adjacent sibling. When that happened, I really wasn't sure what to do other than go on a deep react dive. It's not clear how to debug stuff like that.
I came to realize that I had confused the reconciler. The fix is basically to just use the key= attribute everywhere, not just in arrays.
Here's a minimal-ish repro of the issue I ran in to. It's totally possible that I'm doing something "obviously" wrong. However, I've spent more than a couple of hours reading through docs trying to figure out what it is. I'm not seeing it.
I assume the issue here is that you are rendering a single nameInput instance in two places.
This is definitely not idiomatic react and I can't ever think of seeing this in the wild. Just render two instances. If you want the value synced then it should be a controlled component, where the locked state is passed in as a prop.
> If you want the value synced then it should be a controlled component, where the locked state is passed in as a prop.
This is the kind of stuff that's difficult for me to wrap my mind around. If I have to remember to "do it this way, but not that way", that's mental overhead. Especially when it's difficult to articulate exactly under what circumstances this problem occurs.
Obviously, there are plenty of people that have no problem with it. However, my first inclinations seem to be more likely to be those that React has problems with. I'm having a difficult time "thinking in React".
I'm not sure this is anything specific to react? Its just a question of internal vs external state. Internal state gets managed by the component itself, external state gets managed by some ancestor in the tree. One component's internal state is another's external state. No different to objects or any other data modelling exercise imo.
As for rendering a single instance in two places, you'd see weird behaviour trying to do the same with raw DOM element instance (well not so weird as not being able to render in two places).
No. Some technologies use paradigms that are much more natural to me. Of course, this will vary from person to person. I'm not saying that anyone should stop using react. I'm just saying that I find it to be difficult. Specifically more difficult than other technologies.
Been working with React since 2014. That is the damndest thing ever, especially that it doesn't even throw a warning.
It seems like an identity confusion issue where the VDOM diff is ambiguous, and React resolves it in the "wrong" way. Adding keys to each `LabeledInput` resolves the issue, but I'm surprised that the runtime doesn't complain when you create the inputs without keys.
then it complains that there's no key prop and the issue persists. This shows it's because of confused identity. In the example, it doesn't complain because it doesn't understand that {name}{confirmation}{request} is essentially an unrolled loop.
is basically a hidden render loop. If you had something like
const inputs = [name, confirmation, request]
and rendered that via inputs.map() (or just {inputs}), it would have complained about the missing key prop. React can't seem identify which state belongs to which item in the "iteration".
Yea, I was startled by the issue at first, but once I checked it in more detail it took me like 5min to figure out what was going on.
I'll grant the particular example or edge case is not available in the public docs, but it's extremely easy to intuit what is happening and relate it to the requirement of list components needing keys.
Like I replied to OP, you would be in all likelihood using arrays anyway, instead of this contrived pattern.
I’ve been coding in React for a few years and I’ve never seen anything like this. Bookmarking this so I can take a look tomorrow and also in case someone provides an answer.
I seem to have a talent for coming up with things that shouldn't be, can't be, or are difficult to express in react. Note that I'm not particularly interested in other ways of writing this that would work. I now know several. I'm more interested in simple general rules that one could follow to stay out of trouble.
> I'm more interested in simple general rules that one could follow to stay out of trouble.
I don't know what to tell you, just don't do this?
I've been working professionally for years in React and have never encountered this particular issue. Once I've gotten to to it this morning with fresh eyes it's taken me like 5min to understand - React sees this as a list of the same element, which requires keys - this on the other hand is extremely common and well documented, so even a junior could intuit it.
This is a contrived example and as a moderately experienced developer you would almost certainly reach for the idiom, which would be rendering the input as a list with a map, in which case you would see clearly what's going on, get a warning, and a clear mapping to the official docs [1]
As far as footguns go, I think this is a weak and contrived example. I get why one would not want to work with React - maybe they don't like JSX, or the lack of baked-in state management, that there are a million ways to do the same thing, the general philosophy of the framework, etc.
But I've worked with many other technologies on the front and the back end and not only have I seen infinitely worse than this, I can't think of a technology where if you try really hard to break it, you won't find ways to do so.
I eventually did figure out what's going on. I did figure out that using key= solves it. I also found I could use class components and make the three labeled instances in the constructor. That gives them a long enough lifetime to stay consistent also.
I'm not trying to tell anyone else they shouldn't use react. It's great that so many find it to be so productive.
You might say I dislike the general philosophy of react. I would rather choose whether I'm using 1-way or 2-way binding than being told. I actually have come around on JSX. I think it's pretty good now.
As for being weak and contrived, I don't know what to tell you. This honestly seems like a natural way to write this. I'm a react beginner. When I ran into this, it took me some time to figure it out, but I did eventually. I suppose another part of the philosophy I don't like is entire premise of virtual DOM and reconciliation. It creates another layer of concerns the developer needs to think about. This kind of stuff should be an implementation detail. Instead, you have to remember to use an array rather than unrolling. Or just use keys everywhere. More precisely, maybe you don't need to. But I would need to.
Honest question, why? The problem one always runs into in client side apps is you need various features like conditionals and looping when rendering your HTML. This has lead to a proliforation of templating languages that half-assedly implement these features. Moving to using a full programming language for generating your HTML removes the need for janky inconsistant templating languages.
Browsers support HTML and JS (and a few other things not relevant to this point).
Neither HTML or JS on its own will do what you're describing. HTML doesn't allow binding to a data source. JS doesn't allow you to write HTML declaratively. So, people build abstractions.
If an abstraction ever became popular enough and futureproof enough, there could be a case for supporting it natively. But I don't know of anything that currently exists and does what you're describing.
Natively no, but writing some JS code that will take an array of objects and turn it into a DocumentFragment is a trivial exercise. And once you're representing your HTML as data, looping and data binding are trivial.
You're right. But how often do you want to rewrite that code? It may be worth accepting a few -isms (and the associated performance hit) in order to be able to write something like this instead of having to bang out the imperative version:
What are you talking about? That's the exactly the purpose of jsx - manipulate html with straightforward javascript. and jsx is just a wrapper for React.createElement().
JSX isn't HTML. Is it truly less cognitive burden to have a language that looks like HTML but isn't? With properties changed because they're reserved words? And with control statements from other languages supported inline?
If someone gave me a language that looks like Lisp but with car and cdr renamed to something else, is that really making my life easier?
What cognitive problem do you have? It's just syntax sugar to let you easily manipulate the dom tree. Generating dom nodes and intertwined logic becomes trivial when you have jsx. If u want a list u can do dataList.map(data -> SomeComponent); or do ifTrue ? Component1 : Component2; or even use a function to return conditionally with a switch.
JSX is not HTML because it need to blend logic and HTML seamlessly. React is not static site builder, it's an app builder. If your project doesn't need this sure go ahead. Otherwise are there much better choices?
I find JSX is only straightforward for the simple cases. Often you wind up with unreadable, convoluted garbage because someone was trying to be clever with too many ternary operators, etc.
If you can refactor JSX with simpler js code then you should do that. It's just js expression. If u find reading js expression is harder than all those custom operators in other template languages, you can always switch.
Yes, that's true. I don't see why it's significant though. There doesn't seem to be any inherent reason why an HTML-hosted DSL is more difficult to learn or use.
What custom syntax? You don’t even need to use it, but 100% of the time I do, the custom syntax implementation is vastly simpler than any alternative. I would love an example that contradicts my experience.