5 ms·
and if that expression-body is wrapped within the render() method.
by 9wzYQbTYsAIc 5y ago
and if that expression-body is wrapped within the render() method.
- eyelidlessness 5y agoOkay: only evaluates <Anything /> 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 && <Anything /> || <Fallback /> } 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 && <Anything /> || <Fallback />; Or even just as an expression statement: someBool && <Anything /> || <Fallback />;
- 9wzYQbTYsAIc 5y ago> It doesn’t matter where the expression is placed, it’s the same if you assign it to a variable If you separate the concern of the condition definition from the conditional rendering, by pulling the conditional’s definition into a variable, you do get enhanced portability, though. Much easier to port between languages and frameworks if your conditional definition can be copy-and-pasted out without having to mess with untwining the previous developers expression statements.
- eyelidlessness 5y agoI’m not sure whether I agree or disagree with this. But I do want to clarify that my intent was not to argue for or against conditional expressions in any code position, only to address the factual question of whether they constitute control flow.
- jameshart 5y agoBut 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.