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>
</>
);
Related
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.
I constantly have issues trying to use code and material-ui elements in react jsx code. Here's a code snippet:
const icols = 0;
const makeTableRow = (
x,
i,
formColumns,
handleRemove,
handleSelect) =>
<TableRow key={`tr-${i}`}>
{formColumns.map((y, k) => (
y.displayColumn ? (<TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>) : null), <-comma added for next line
y.displayColumn ? (cols+=1) : null)
)}
<TableCell>
<IconButton onClick={() => handleSelect(i)} ><EditIcon fontSize='small'/></IconButton>
<IconButton onClick={() => handleRemove(i)} ><DeleteForeverIcon fontSize='small' /></IconButton>
</TableCell>
</TableRow>
I am getting a jsx parsing error, when I add this line above:
y.displayColumn ? (cols+=1) : null)
If I remove the comma at the EOL above it, I still get an error. Basically I can't get a map to exec more than one statement.
If I take out the line and the EOL comma above it, everything works but I don't get a displayed column count, which I require.
I've tried using simple if/else which I am more comfortable with, but I have NEVER been able to get if/else to work in a jsx function. I want to only create a tablecell for a column w/displayColumn flag set to true, and I want a total count of the displayed columns, so I can use it later on (cols).
Is there a way to accomplish this with an if/else statement? Then I can have more than 1 statement in the if clause. The ternary operator only allows 1 statement, and I can't find anywhere what maps limitations are.
Thanks in advance for your help!
You can do something like this. You can open the open the arrow function body in map and put return JSX and do the cols increment there. Instead of having two ternary operator checks for the same condition, we can have just one conditional statement.
<TableRow key={`tr-${i}`}>
{
formColumns.map((y, k) => {
if (y.displayColumn) {
cols += 1;
return <TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>
}
return null
})
}
<TableCell>
<IconButton onClick={() => handleSelect(i)} ><EditIcon fontSize='small'/></IconButton>
<IconButton onClick={() => handleRemove(i)} ><DeleteForeverIcon fontSize='small' /></IconButton>
</TableCell>
</TableRow>
Basically I can't get a map to exec more than one statement.
You can't execute more than one expression inside a arrow function definition, instead use regular declarated functions
{formColumns.map((y, k) => {
y.displayColumn ? (cols+=1) : null;
// Return what you want to render
return y.displayColumn ? (<TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>) : null
}}
There are only two types of arrow function
arrow_function = () => "i will be returned"
// This way you declare only one expression after the arrow and it is returned
and
arrow_function = () => {
// This is a regular logic function
text = "i will be" + " returned";
return text;
}
EDIT 1: Add conditionals between JSX
There are two ways i know to do it
const App = () => {
return (
<div>
<h2>First form</h2>
<FirstForm true={true} />
<hr />
<h2>Second form</h2>
<SecondForm true={false} />
</div>
)
}
const FirstForm = props => {
// This way is just a ternary conditional
return (
<div>
{props.true
? <span className="success">True condition matched</span>
: <span className="danger">False condition matched</span>
}
</div>
)
}
const SecondForm = props => {
// This way uses a anonymous function executed in runtime
return (
<div>
{(() => {
let message = "Hello";
message += " World, from an auto executed anonymous function";
return (
<span className={props.true?"success":"danger"}>{message}</span>
)
})()}
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
.success {
color: darkgreen;
}
.danger {
color: #5e181b;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Ok psiro, so I looked at your examples, which all work in your situation. However, as soon as I apply one to my scenario, I still get a syntax error. Like here:
<TableBody>
{(() => {
console.log('data = ' + JSON.Stringify(data, null, 2) + '.'));
return ((data.length > 0) ? (
data.map((x, i) => row(
x,
i,
formColumns,
handleRemove,
handleSelect,
editIdx
))) : (<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>) )
})()}
</TableBody>
And this is the problem I have w/anonymous functions. They create unmaintainable code. I am not doing anything different than your example. Just TWO js statements inside the code you presented. Your code works, mine returns a syntax error.
And why do I even NEED a double-anonymous function to have 2 simple js statements inside an if statement? Why does your code work, and mine not?
Addendum:
Ok, so I made some inferences based on your code and realized I had added yet ANOTHER anonymous function (the map statement) into the code. I reworked it into this, which compiled:
{(() => {
console.log('data = ' + JSON.Stringify(data, null, 2) + '.');
if (data.length > 0) {
return (data.map((x, i) => row(x, i, formColumns, handleRemove, handleSelect, editIdx)))
}
return(<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>)
})()}
The fact that it looks completely unmaintainable is irrelevant I guess. But it doesn't matter because it STILL doesn't work! Now I get a 'JSON.stringify is not a function' at runtime, which is ridiculous of course. Why can't I get a simple console.log to work in reactjs?
ADDENDUM:
Ok, I fixed the issue thanks to all the help. For anyone else that has an issue w/multiple statements inside an anonymous function, if you want to do it, you need to add a return statement so the function knows what result to return.
<TableBody>
{(() => {
console.log('data = ' + data + '.');
if (data.length > 0) {
return (data.map((x, i) => row(x, i, formColumns, handleRemove, handleSelect, editIdx)))
}
return(<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>)
})()}
</TableBody>
That includes when you have an anonymous function inside another anonymous function. Hope this helps anyone else having this problem.
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>
);
}
Hello I have a component which doesnt return anything. Im following a tutorial and the person is using newer syntax which confuses me a bit. The component looks like this:
const Alert = ({alerts}) => alerts !== null && alerts.length > 0 && alerts.map(alert => (<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg}</div>));
I simply want to know how to write this without it being single line. So i can see what's going on. Much appreciated in advance. For as far as i am aware you always need to return something.
const Alert = ({ alerts }) => {
if (alerts !== null && alerts.length > 0) {
return alerts.map(alert => (
<div key={alert.id} className={`alert-${alert.type}`}>
{alert.msg}
</div>
));
}
return null
};
Things at play here are:
Arrow Functions
Array.Map
JSX
Template Literals
Basically its a component that takes in an alerts property (Array) as a prop (<Alert alerts={[...]} />). It checks whether the passed array is present and is not empty and then maps over it. For every item in the array, we are rendering a div containing the alert message.
Hope this helps!
Very roughly (i.e., untested):
const Alert = ({alerts}) => {
if ((alerts === null) || (alerts.length === 0)) {
return null
}
return alerts.map(alert => (
<div
key={alert.id}
className={`alert-${alert.type}`}
>
{alert.msg}
</div>
))
}
const Alert = ({alerts}) => {
if (!alerts || !alerts.length) return null
return (
<>
{alerts.map(alert => (
<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg}</div>
)}
</>
)
}
I think what you are struggling with is generally the one-liner syntax, which doesn't need a return if there are no braces present.
What I mean is that this line
return alerts.map(alert => {
return (<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg} </div>)
})
Would be the same as this line
return alerts.map(alert => (<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg} </div>))
I can do
<p>Company: {{this.state.user.company}}</p>
but sometime company has no value. So how should I hide the entire if the property of company is null?
I tried
<p>({this.state.user.company} ? 'Company: ' + {this.state.user.company} : '')</p>
But it doesn't work.
React doesn't render falsy values, so you can use short-circuit evaluation. If this.state.user.company is null, it will be ignored by react. If it's truthy, react will render the element after &&.
render() {
return (
<div>
{this.state.user.company &&
<p>Company: {this.state.user.company}</p>
}
</div>
);
}
Alternative syntax to Ori Drori's answer (I find this a bit easier to read):
render() {
return (
{this.state.user.company ? <p>Company: {this.state.user.company}</p> : null}
)
}
Another alternative:
render() {
if (!this.state.user.company) return (<p>Loading...</p>)
return (
<div>
<p>Name: {this.state.user.company.name}</p>
<p>Address: {this.state.user.company.address}</p>
<p>Creation date: {this.state.user.company.creation}</p>
</div>
)
}
You could also use the following for a short handed format:
render() {
return (
{this.state.user.company ?? <p>Company: {this.state.user.company}</p>}
)
}
Reference Nullish coalescing operator (??)