5 ms·
A problem is that you can only declare intermediate constants in a statement context, not an expression context. And with React, more and more JS devs are spend
by brundolf 4y ago
A problem is that you can only declare intermediate constants in a statement context, not an expression context. And with React, more and more JS devs are spending time in expression contexts
Example:
return (
<div>
{foo(bar(stuff))}
</div>
)
There's no way to break out inline intermediate constants here; you have to bail out and do it up above the `return`. In this case that may not be too bad, but when you've got a hundred lines of JSX, things start getting really spread out
- shadowgovt 4y agoBut that's a symptom of issues with React, not issues with JavaScript. React's declarative model makes it easy to write unreadable spaghetti React declarations that are nested ten levels deep. Nobody should be adding features to JavaScript to encourage that. ("Please, I'm begging you, for the love of sanity... Refactor into more than one component. Just one time. Look, functional components even make that cheap and easy now. Please please please, just take some of that nesting and put it in a new component.")
- brundolf 4y agoHighly disagree on two counts: > that's a symptom of issues with React, not issues with JavaScript IMO keeping as much as possible in an expression-context is preferable, even without React, because it simplifies control-flow and avoids mutation. The main problem in this case, as I see it, is that javascript doesn't fully support that style- it could and should have a feature that allows intermediate constants (but not variables!) inside expressions. (It should also have something better than ternaries for expressive conditionals, but that's a separate topic) > Refactor into more than one component Plenty of ink has been spilled here in the past about splitting functions when there's a real conceptual boundary, not just when they "get too large", and how otherwise keeping your code together in one place can actually make it easier to follow because you don't have to jump around all over the place. So I don't really want to get into all that again here, but suffice to say that's my stance on the subject.
- shadowgovt 4y agoI mean, we could refrain from talking about the need to "jump around," but that's the crux of the issue: modern IDEs (like vscode) include "peek" functionality to look at a definition inline. No need to jump around at all. And a thousand-line component has a thousand lines of context it could be pulling in; reasoning about that level of complexity rapidly gets complicated. If you have some complicated expression to say inline in a React declaration, pull it up to the preparatory layer. If there are performance reasons not to do that, push it down into a subcomponent.
- dns_snek 4y agoTechnically, you should be able to write something uniquely terrible like this ;) return ( <div> {(() => { const barStuff = bar(stuff); return foo(barStuff); })()} </div> )
- brundolf 4y agoYeah, JS programmers sometimes work around this and similar language gaps by making an inline function and immediately calling it (because that gives you a statement context inside of an expression context, which isn't normally possible). But IMO it's very rarely worth the hit you take to readability
- hajile 4y agoThey should repurpose `do` so that `do {}` (without the `while`) is an expression that you can put statements inside and return the last statement. It would be great if we had expression if..else too (instead of just the tertiary operator)
- TheAngush 4y ago> They should repurpose `do` so that `do {}` (without the `while`) is an expression that you can put statements inside and return the last statement. There's a proposal for precisely that. Unfortunately, only Stage 1 though. https://github.com/tc39/proposal-do-expressions https://github.com/tc39/proposal-do-expressions
- layer8 4y agoThe way to fix that then would be to introduce a way to create named values within an expression. E.g. have something like let foo = bar in <expression> be an expression.
- nitwit005 4y ago> There's no way to break out inline intermediate constants here; you have to bail out and do it up above the `return`. Which seems fine. There's not an obvious gain to having one giant super-complex return statement.
- captainmuon 4y agoBut isn't then the problem that JS doesn't offer more expressive function contexts? Some languages like Nim allow you to use blocks in place of expressions; the last expression in the block determines the return value. You can also use `if` as an expression. No need to introduce a separate syntax for this case. (Although I do like piping in bash, but I don't think it is a good idea for JS.) Also sometimes you should just give stuff a temporary name, and treat React like a templating language.