3 ms·
But the short circuiting doesn’t matter. You could go let x = <Anything />; return someBool && x; And the result (assuming well behaved react code) wou
by jameshart 5y ago
But the short circuiting doesn’t matter.
You could go
let x = <Anything />;
return someBool && x;
And the result (assuming well behaved react code) would be the same. <Anything /> is just a literal expression. It doesn’t matter whether it gets evaluated or not.
You’re not using && shortcircuiting to prevent <Anything/> 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 ‘using shortcircuiting for control flow’. It’s just using && as an operator in an expression evaluation.
- eyelidlessness 5y agoEdit: 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. 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?”
- deleted 5y ago[deleted]
- rimunroe 5y ago> 1. Execute the code (duh), which at minimum uses CPU resources 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.
- jameshart 5y agoI'm sorry, but you're just mistaken about how JSX works. <Foo /> 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 = <UnrenderedComponent/>; return "This will get rendered"; } ReactDOM.render( <RenderedComponent />, document.getElementById('container') ); I'll save you copy/pasting - here's a jsFiddle: https://jsfiddle.net/gr4kxq81/ https://jsfiddle.net/gr4kxq81/ That code unconditionally includes the evaluation of <UnrenderedComponent/> 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 && <MyComponent/> 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.