Earlier quoted context omitted.
Micro-optimisations aren't useful. If you get to the point where the performance cost of inline functions is a bottleneck, you probably shouldn't be using React at all.
Maybe, but I just prefer to have a named function defined with a useCallback and just call it.
Advice on JSX Conditionals
111–120 of 127 posts
Re: Advice on JSX Conditionals
#112I've always found these approaches to writing conditions in JSX to be terrible. Wouldn't it be nice if JavaScript were an expression-oriented language? Then you could just write: {if (gallery.length) { }} There has been a "do expressions" proposal [0] for many years, which addresses this (though it is more verbose). I hope it will be accepted some day. [0] https://github.com/tc39/proposal-do-expressions
Re: Advice on JSX Conditionals
#113Earlier quoted context omitted.
Okay: only evaluates if someBool is true. The value of someBool quite literally controls which code path is taken. It’s even more clear with a fallback: { someBool && || } Which would more idiomatically be written as a ternary conditional, but still. It doesn’t matter where the expression is placed, it’s the same if you assign it to a variable: const el = someBool && || ; Or even just as an expression statement: some…
But the short circuiting doesn’t matter . You could go let x = ; return someBool && x; And the result (assuming well behaved react code) would be the same. is just a literal expression. It doesn’t matter whether it gets evaluated or not. You’re not using && shortcircuiting to prevent from being evaluated - it doesn’t matter if it gets evaluated. You are using it to decide which value to return. This really isn’t ‘usi…
- - -
Of course it matters.
“Well behaved react code” isn’t side-effect free, as much as it tries hard to look almost like it is. You can write perfectly idiomatic components which follow all best practices, and evaluating a component when you don’t intend to use it will still:
1. Execute the code (duh), which at minimum uses CPU resources
2. Perform relevant hooks and call lifecycle methods, including those which have side effects (hint: “effect” is in the hook’s name, for this reason): starting timers, loading resources, calling non-React APIs, pretty much anything goes by design, even if you follow all the rules and other best practices.
3. Prepare for a new, potentially concurrent, render. This may speculatively interrupt/pause a render in progress which would otherwise complete without interruption. Which may, in turn, cause seemingly unrelated components to be called again, cascading this entire set of potential side effects to them, and so on.
4. Call any components in that cascade whether they’re well behaved in your control, or epic shit show dependencies.
Being in an expression position does not mean it’s side effect free. If you don’t believe me, run this code:
const isPure = (value) => (
value = 'NOPE',
console.log('There is no code block in sight, this function has zero statements. Is it pure?', value),
value
);
isPure('yeah?');
And sure, React and most JSX implementations are designed to make evaluating JSX side effects local as much as possible. But that’s limited because it’s exposed to APIs not under its control by design, first of all. And more importantly, I would hope that, on HN of all places, a knowable answer to a factual question “is code executed?” is not treated as subjective. This is the exact same question as “is it control flow?”Re: Advice on JSX Conditionals
#114It doesn’t necessarily have the same benefits in React, but folks ought to consider using components for control flow, like SolidJS does[1]. 1: https://www.solidjs.com/docs/latest/api#control-flow
Agreed. I particularly like the look of their ` / ` component[1]: Not Found }> Which doesn't seem to have an analog in the React babel-plugin[2] or standalone lib[3] [1] https://www.solidjs.com/docs/latest/api#%3Cswitch%3E%2F%3Cma... [2] https://github.com/AlexGilleran/jsx-control-statements [3] https://github.com/samuelneff/react-control-flow
Re: Advice on JSX Conditionals
#115Earlier quoted context omitted.
Can’t speak for GP, but for me, because: { someBool && } … only renders if someBool is true.
What if you consider it as ‘only returns a data structure that requests the rendering of if someBool is true’? If you write console.log(someBool && “anything”) Are you altering the control flow because the console window will call a different bit of font evaluation code to render “anything” instead of “false”? Or are you just conditionally evaluating an expression that results in different data that causes different…
someBool && console.log(“anything”)
Hope this helps.Re: Advice on JSX Conditionals
#116Earlier quoted context omitted.
But the short circuiting doesn’t matter . You could go let x = ; return someBool && x; And the result (assuming well behaved react code) would be the same. is just a literal expression. It doesn’t matter whether it gets evaluated or not. You’re not using && shortcircuiting to prevent from being evaluated - it doesn’t matter if it gets evaluated. You are using it to decide which value to return. This really isn’t ‘usi…
Edit: I read this back to myself and realized it may come off as harsh or mean. I don’t intend it as such, and I apologize if it’s received that way. I think being precise about this is worth pursuing, for the sake of both developers thinking about it and users experiencing what we build. - - - Of course it matters. “Well behaved react code” isn’t side-effect free, as much as it tries hard to look almost like it is.…
Re: Advice on JSX Conditionals
#117Earlier quoted context omitted.
But the short circuiting doesn’t matter . You could go let x = ; return someBool && x; And the result (assuming well behaved react code) would be the same. is just a literal expression. It doesn’t matter whether it gets evaluated or not. You’re not using && shortcircuiting to prevent from being evaluated - it doesn’t matter if it gets evaluated. You are using it to decide which value to return. This really isn’t ‘usi…
Edit: I read this back to myself and realized it may come off as harsh or mean. I don’t intend it as such, and I apologize if it’s received that way. I think being precise about this is worth pursuing, for the sake of both developers thinking about it and users experiencing what we build. - - - Of course it matters. “Well behaved react code” isn’t side-effect free, as much as it tries hard to look almost like it is.…
In this case it really is quite a minimum use of CPU, as React's createElement function doesn't do a whole lot. As far as I know, in a production build it's really just going to do a teeny amount of work to create an object (which looks like {type: Login, props: {}, /* ...some other properties */}). "Evaluating a component" isn't something the user ever does directly. The React runtime is the only thing which ever invokes a component's render method.
> 2. Perform relevant hooks and call lifecycle methods, including those which have side effects (hint: “effect” is in the hook’s name, for this reason): starting timers, loading resources, calling non-React APIs, pretty much anything goes by design, even if you follow all the rules and other best practices.
> 3. Prepare for a new, potentially concurrent, render. This may speculatively interrupt/pause a render in progress which would otherwise complete without interruption. Which may, in turn, cause seemingly unrelated components to be called again, cascading this entire set of potential side effects to them, and so on.
> 4. Call any components in that cascade whether they’re well behaved in your control, or epic shit show dependencies.
It won't do any of these things. React won't try to actually render a component (call its render function) unless an element referring to it ends up being returned by the render function of another component which gets rendered.
Re: Advice on JSX Conditionals
#118Earlier quoted context omitted.
But the short circuiting doesn’t matter . You could go let x = ; return someBool && x; And the result (assuming well behaved react code) would be the same. is just a literal expression. It doesn’t matter whether it gets evaluated or not. You’re not using && shortcircuiting to prevent from being evaluated - it doesn’t matter if it gets evaluated. You are using it to decide which value to return. This really isn’t ‘usi…
Edit: I read this back to myself and realized it may come off as harsh or mean. I don’t intend it as such, and I apologize if it’s received that way. I think being precise about this is worth pursuing, for the sake of both developers thinking about it and users experiencing what we build. - - - Of course it matters. “Well behaved react code” isn’t side-effect free, as much as it tries hard to look almost like it is.…
does not translate into a call to Foo(). It translates into React.createElement(Foo).
And Foo will only be called if the element returned from that call winds up being examined by some renderer like ReactDOM, mounted as a component, and actually rendered.
Here:
function UnrenderedComponent() {
console.log("UnrenderedComponent does not get executed");
React.useEffect(() => {
console.log("this effect never runs")
});
return "This won't get rendered"
}
function RenderedComponent() {
console.log("Rendered Component running")
React.useEffect(() => {
console.log("this effect runs")
});
const x = ;
return "This will get rendered";
}
ReactDOM.render(
,
document.getElementById('container')
);
I'll save you copy/pasting - here's a jsFiddle: https://jsfiddle.net/gr4kxq81/That code unconditionally includes the evaluation of in the context of a render method.
But the UnrenderedComponent() function does not get called, its useEffect call never happens, its effect code never gets executed, because the resulting element doesn't make its way back to ReactDOM to be mounted.
someBoolean && is not control flow, it's a simple expression that conditionally evaluates to an instruction to either not render anything, or to mount and render a MyComponent. It's cheap and side effect free.
My comment about 'assuming well behaved React code' was more directed at the fact that technically you can plug in a custom JSX pragma so you might not just be handing it to React.createElement, in which case all bets are off for what happens. But React doesn't call render methods for components unless they're mounted.
Re: Advice on JSX Conditionals
#119Earlier quoted context omitted.
Edit: I read this back to myself and realized it may come off as harsh or mean. I don’t intend it as such, and I apologize if it’s received that way. I think being precise about this is worth pursuing, for the sake of both developers thinking about it and users experiencing what we build. - - - Of course it matters. “Well behaved react code” isn’t side-effect free, as much as it tries hard to look almost like it is.…
I'm sorry, but you're just mistaken about how JSX works. does not translate into a call to Foo(). It translates into React.createElement(Foo). And Foo will only be called if the element returned from that call winds up being examined by some renderer like ReactDOM, mounted as a component, and actually rendered. Here: function UnrenderedComponent() { console.log("UnrenderedComponent does not get executed"); React.useE…
No, I’m not. JSX doesn’t do anything. But it’s an expression and evaluated according to the rules of JS expressions. You might expect React or whatever to evaluate it one way today, and it can be evaluated another way tomorrow. React.createElement isn’t the API you’re using, neither is react/jsx-runtime. You’re using an expression with some special angle brackets and curly braces. You have no idea if your component is being called, but semantically you have every reason to believe it is and will be.
Bool && otherExpression is control flow because it’s specifically defined as an expression in the host language. Anything else is assuming compiler magic you were never promised.
Re: Advice on JSX Conditionals
#120Earlier quoted context omitted.
You can add do-expression proposal support in .babelrc: {do { if (user) { } else { } }} https://babeljs.io/docs/en/babel-plugin-proposal-do-expressi...
Or, no need to enable anything: {user ? : }