I want to display a component depending on a variable. The variable should be able to hold a flexible amount of conditions/types.
Example:
I want to display my component if test1 === false or test2 equals a number greater than 0. But also should allow to expand. Here is what I am trying so far.
const test1 = false
const test2 = 10
const conditionVar = test1 === false || test2 > 0
return (
{
conditionVar ? <MyComponent /> : null
}
)
Questions would be if this is good or bad practise? Can I extend this for example if I needed test3, test4... variables in the future as conditions? Will it be safe and run as expected every time?
That's common practice when it's inside a larger JSX structure, although with your specific example there's no reason to be indirect, just:
return conditionVar ? <MyComponent /> : null;
If you know conditionVar will be null, undefined, or false (specifically) when you don't want to render or any truthy when you do, you can also do:
return conditionVar && <MyComponent />;
Or in a larger structure:
return <div>
{/*...something...*/}
{conditionVar && <MyComponent />}
</div>;
But another option is to just set a variable to the thing you want to render:
const component = !test1 || test2 > 0
? <MyComponent />
: null;
then when rendering, use component:
return component;
or in a larger structure:
return <div>
{/*...something...*/}
{component}
</div>;
They're all fine in context.
Like others have mentioned, you approach is fine. However, I would argue that in a more complex situation, it would be more readable to put the different conditions and renders one after another.
Also, you can utilise early returns so that if there is no data to display, your component will exit immediately.
Here's an example:
if (noData) {
return null;
}
if (condition1) {
return <Component1 />;
}
if (condition2) {
return (
<div>
<Component2A />
<Component2B />
...
</div>
);
}
Having this in mind, I would rewrite your example like this:
if (test1 && test2 <= 0) {
return null;
}
return <MyComponent />;
Note: test1 is not precisely the same as the negative of test1 === false but i believe that's what the intention was.
Related
In my React Native app, I want to render a <View> conditional on variable var. There are two ways I've tried doing this:
1)
{var && <View/>}
{var ? <View/> : null}
Is there an advantage of one over the other?
The difference is in method 2, the falsey expression can be rendered. Take this example, which will render <div>0</div> instead of an empty div as you might expect.
render() {
const count = 0;
return (
<div>
{count && <View />}
</div>
);
}
Conditional rendering docs.
In Javascript, it seems like a general practice for an if statement to check if a favorable condition is met first,
e.g. a parameter or variable is presently defined and available for consumption:
const funcName = (necessaryParam) => {
if (necessarryParam.length > 0) {
console.log('condition met!');
return;
}
console.log('condition not met!');
return;
}
In React, I see opportunities for positive-affirmation conditionals to skip an entire return statement:
const Component = (props) => {
if (props)
return (
<YourComponent withProps={props} />
)
}
to components that require parsing through several lines of code before saying they don't have enough information to function optimally:
function YourComponent(props) {
return (
{ props && (
<ComponentEveryoneWantsThatNeedsProps withProps={props} />
)
}
{ !props && (
<ComponentThatTellsYouYoureScrewed />
)
)
}
In that general context, if I have a more sizeable part of a component that will render in the condition of the affirmative, compared to a smaller part rendering in the condition of the negative, should I check to see if the affirmative condition is not met before React parses the larger affirmative-condition codeblock? (Is this considered "good practice"?)
e.g. it's easier to check if you DON'T have what I need, because I can tell you to bugger off sooner...:
function ConditionallyRenderedComponent(props) {
return (
{ !props && (
<div>
<OneComponent />
</div>
)
} // vs
{ props && (
<div>
<FirstComponent>
<H1>
<SecondComponent />
</H1>
</FirstComponent>
</div>
)
}
)
}
Obviously these are extremely contrived examples, but hopefully my question makes sense.
Is there an argument for exposing only the simplest thing first? Is there a particular way to do it that you find works best?
Does it really even matter?
Any interesting or helpful material you've picked up regarding structuring conditionals in React you'd like to share?
There are multiple considerations for ordering of conditional checks. Some examples:
Performance optimizations: e.g. filtering invalid inputs:
function calculateValue (...inputs) {
if (!inputs.every(n => typeof n === 'number')) return NaN;
// ...computationally expensive logic
return expensiveResult;
}
Throwing an exception at an impasse to ensure that continuation only occurs with a valid state:
function findNestedSiblings () {
// ...
const element = document.querySelector(/* selector */);
if (!element) throw new Error('msg');
// element exists
// continue...
}
Beyond performance optimizations, sometimes the structuring of conditionals can help with code readability (this begins to enter the territory of opinion). If you can handle a terminal condition first, (e.g. one resulting in return, throw, break, continue, yield, etc.), you often don't need an else block and can maintain your code at top-level indentation in the scope: I find this very useful and often aligned with the performance ordering.
EDIT: Obsolete, I made some mistake in another piece of code and the received data had the wrong data type.
I have a variable that stores the index of a selected item. I used a conditional expression based on that variable to add/remove a class name so said item is rendered in a distinguishing way. I boiled down the problem to this snippet:
function App() {
const [selectedItem, setSelectedItem] = setState(-1);
setSelectedItem(0);
console.log(selectedItem);
return (
<>
{selectedItem !== 0 && <p>no item selected</p>}
{selectedItem === 0 && <p>item {selectedItem} selected</p>}
</>
);
}
This snippet always displays that no item is selected.
The hook is called useState, not setState.
Calling setSelectedItem inside the render function will trigger an infinite loop. You need to move it to an effect hook so it only runs one.
export default function App() {
const [selectedItem, setSelectedItem] = useState(-1);
useEffect(() => {
setSelectedItem(0);
}, []);
console.log(selectedItem);
return (
<>
{selectedItem !== 0 && <p>no item selected</p>}
{selectedItem === 0 && <p>item {selectedItem} selected</p>}
</>
);
}
What is setState ? Do you mean useState ? And also, you shouldn't update the state like this, you should do it in a useEffect, and use an empty array as dependency, so it will run only once, when your component is being mounted:
useEffect(() => {
setSelectedItem(0);
},[])
Then it is working like a charm
Replace === and !== with == and !=, respectively, and voila, it works. Alas, a warning is reported that one shall use === instead.
selectedItem is an array, apparently primitives make bad references. Still, it is bizarre to some extent that inside <p> the variable is unboxed automatically, while for evaluating === it isn't and thus an array is compared to a primitive, which is not true, no matter the values. == compares every shit in JS that you feed it with, so here it works.
Hope, this saves somebody 2 hours of debugging.
If somebody has a correct workaround for this, please share below.
I want to render some part of Html only if one of the variable is true. I have seen examples where I can return the whole element but I only want a if condition on one part of the html. I only want to show with 10 lines if one of the variables is true but html with 500 lines is common. Can I do that in return function?
const getCustomers= (props) => {
useEffect(() =>{ do something...});
return (
<>
if(test === true){
<div> 10 lines</div>
else
{
do not show this div
}
}
<div> 500 lines</div> // Common
</>
)
};
Conditional rendering is only supported using ternary operator and logical and operator:
{
something ? '10 lines' : '500 lines'
}
{
something && '10 lines' || '500 lines'
}
if-else statements don't work inside JSX. This is because JSX is just syntactic sugar for function calls and object construction.
For further details, you may read this, and the docs
Try to avoid logic inside of your return statements.
You can assign your conditional output to a JSX value, and always render it.
const Customers = () => {
const optionalDiv = test === true && <div>10 lines</div>;
return (
<>
{optionalDiv}
<div>500 lines</div>
</>
);
};
you can use conditional (ternary) operator
return (
<>
{ test === true ? (<div> 10 lines</div>) : null }
<div> 500 lines</div>
</>
)
I think just doing it like this should do it -
return (
<>
{test? <div> 10 lines</div> : null}
<div> 500 lines which are common</div>
</>
);
I wonder how can use two state based booleans inside of the conditional rendering . For example i want to render a certain <div> element if one of the conditions are truthy and otherwise don't render it
Example :
{
this.state.visible && this.state.checked &&
<div>
...
</div>
}
In order to display my error message i use this example , but init i have the .length of the object so it is easy to use like :
{
this.state.ErrorMessage.length > 0 &&
<p>Error 404</p>
}
Can somebody give me heads up ? I am a little bit confused .
You can follow your way by parenthesis, to check both are true:
{
(this.state.visible && this.state.checked) && <div>...</div>
}
if you want one of is true:
{
(this.state.visible || this.state.checked) && <div>...</div>
}
Use it as a separate function which returns the components based on condition.
Example :
renderConditionalComponent() {
const { visible, checked } = this.state;
if (visible || checked) {
return <Component1 />;
}
// There could be other condition checks with different components.
// ...
return null;
}
render() {
// ...
return (
<div>
{this.renderConditionalComponent()}
{/* other components, etc */}
<OtherComponent />
</div>
);
}