Can you use a if statement in JSX like this?
var chartGraphContent =
<div className={"chartContent"}>
if(this.state.modalityGraph['nca'] > 0){
<div className={"chart-container"}>
<Chart
chartType="ColumnChart"
data = { this.state.modalityGraph?this.state.modalityGraph.chartData['units']:emptyDataRows }
options={chartOptions}
graph_id="modalitiesChart"
width="100%"
height="250px"
/>
</div>
}
</div>;
Something like above? Is it possible to have JSX based on a condition?
Use conditional rendering, and since you have no else-case, you can use && instead of a ternary operator for brevity:
It works because in JavaScript, true && expression always evaluates to expression, and false && expression always evaluates to false.
Therefore, if the condition is true, the element right after && will appear in the output. If it is false, React will ignore and skip it.
Thus:
<div className={"chartContent"}>
{this.state.modalityGraph['nca'] > 0 &&
<div className={"chart-container"}>
<Chart
chartType="ColumnChart"
data = { this.state.modalityGraph?this.state.modalityGraph.chartData['units']:emptyDataRows }
options={chartOptions}
graph_id="modalitiesChart"
width="100%"
height="250px"
/>
</div>
}
</div>
This will only render JSX if a condition is true. If it is false, React won't render anything. Remember, you have to wrap inline JavaScript expressions in JSX with { … }, you can't just have it inside JSX.
Using if/else statements directly in JSX will cause it to be rendered literally as text, which isn't desired. You also can't use them in inline JavaScript expressions because if statements are not expressions, so this won't work:
{
if(x) y
}
As per DOC:
if-else statements don't work inside JSX. This is because JSX is just
syntactic sugar for function calls and object construction.
We can't use if-else statement or any other statement directly inside JSX, only expressions are allowed.
Expressions inside JSX:
Wou can embed any JavaScript expression in JSX by wrapping it in curly
braces.
To put any expression we need to use {}, so instead of if use && operator or ternary operator for conditional rendering.
By using ternary operator:
var chartGraphContent =
<div className={"chartContent"}>
{
this.state.modalityGraph['nca'] > 0 ?
<div className={"chart-container"}>
<Chart
chartType="ColumnChart"
data = { this.state.modalityGraph?this.state.modalityGraph.chartData['units']:emptyDataRows }
options={chartOptions}
graph_id="modalitiesChart"
width="100%"
height="250px"
/>
</div>
:null
}
</div>;
By using && operator:
var chartGraphContent =
<div className={"chartContent"}>
{
this.state.modalityGraph['nca'] > 0 &&
<div className={"chart-container"}>
<Chart
chartType="ColumnChart"
data = { this.state.modalityGraph?this.state.modalityGraph.chartData['units']:emptyDataRows }
options={chartOptions}
graph_id="modalitiesChart"
width="100%"
height="250px"
/>
</div>
}
</div>;
Better to use with ternary Operator, By doing so you can also add else block to your code.
Try this:
var chartGraphContent =
<div className={"chartContent"}>
{this.state.modalityGraph['nca'] > 0 ?
<div className={"chart-container"}>
<Chart
chartType="ColumnChart"
data = { this.state.modalityGraph?this.state.modalityGraph.chartData['units']:emptyDataRows }
options={chartOptions}
graph_id="modalitiesChart"
width="100%"
height="250px"
/>
</div>
: "<span>Else Block</span>"
}
</div>;
Update (Another method)
and in case for more complex and large condition you can call inline functions too to return your template , in this way you can avoid your code to become messy. here is an example.
var ifBlockCode = function ifBlockCode(){
return (
<div className={"chart-container"}>
<Chart
chartType="ColumnChart"
data = { this.state.modalityGraph?this.state.modalityGraph.chartData['units']:emptyDataRows }
options={chartOptions}
graph_id="modalitiesChart"
width="100%"
height="250px"
/>
</div>
)
}
var elseBlockCode = function elseBlockCode(){
return (
<span>Else Block</span>
)
}
var chartGraphContent =
<div className={"chartContent"}>
{this.state.modalityGraph['nca'] > 0 ?
{this.ifBlockCode} : {this.elseBlockCode}
}
</div>;
Related
i want to create a function or a conditional statement you can say that can show different components based on "If the user have bought products" then show the products components otherwise show "just a simple text like browse or buy products."
<div>
<Bookscard />
</div>
so this is my component, inside the component the purchased products are being mapped. Can i get a conditional statement that can either show this component like ( if user.courses is greater than or equal to 1 then show the component otherwise show a text ) something like this
You can try this:
<div>
{ user.courses.length > 0 &&
<Bookscard />
}
{ user.courses.length > 0 ||
<NoResults />
}
</div>
Or you can keep consistency with && by:
<div>
{ user.courses.length > 0 &&
<Bookscard />
}
{ user.courses.length == 0 &&
<NoResults />
}
</div>
Adding up to #Antoine Baqain's answer, you could use ternary operator too, like this:
<div>
{ user?.courses?.length > 0 ? <Bookscard /> : <NoResults /> }
</div>
I try to set a condition
initialValue = {
this.props.noteviewReducer.isError &&
this.props.noteviewReducer.result.body
}
if (this.props.noteviewReducer.isError) true then show this.props.noteviewReducer.result.body
if not, then not show
Try something like this
<div>
{this.props.noteviewReducer.isError && (
<MyComponent initialValue={this.props.noteviewReducer.result.body} />
)}
</div>
I am getting an error of in the below
Line 56:11: Expected an assignment or function call and instead saw an expression no-unused-expressions
<div className="posts_container">
{
(userPosts.length) ?
(
<div>
{
userPosts.map((post,idx)=>{
<div className="smallPost">
<img className='smallPost_pic' alt='post_img' src={post.imageurl}/>
</div>
})
}
</div>
)
:
(
<h1> No posts Yet </h1>
)
}
</div>
please help me to solve this.
Thanks in advance.
The function that's passed to .map isn't returning anything.
So either add return:
userPosts.map((post,idx) => {
return (
<div className="smallPost">
<img className='smallPost_pic' alt='post_img' src={post.imageurl}/>
</div>
)
})
or replace the curly braces with parentheses:
userPosts.map((post,idx) => (
<div className="smallPost">
<img className='smallPost_pic' alt='post_img' src={post.imageurl}/>
</div>
)
)
As a sidenote, remember to add a key to the div that is returned from the .map function. More about that in React's docs: Lists and Keys
I want to loop through a props screenshots but it's not working for me! I used to do it in other components and it was working. I'm losing my mind :(
please find below my code:
{screenshots && <h2>Hello</h2>}
this works and rendered perfectly.
but when I do a loop like
{screenshots && screenshots.length && screenshots.map(screenshot => {
<div className="container img--container" key={screenshot.id}>
<SVG
className="icon remove--icon"
src={removeCircle}
/>
<img src={screenshot.image} title={"screenshot"} className="p-absolute"/>
</div>
})}
what's inside the loop doesn't get rendered!
and the console doesn't show any error.
please any help?
Missing return!! You can use "()" to return immediate.
{screenshots && screenshots.length && screenshots.map(screenshot => (
<div className="container img--container" key={screenshot.id}>
<SVG
className="icon remove--icon"
src={removeCircle}
/>
<img src={screenshot.image} title={"screenshot"} className="p-absolute"/>
</div>
))}
When using map, you have to be careful what to put after the =>.
If you have to process elements of the array when mapping, do this:
array.map(a => {
// Javascript here
return(
<div>JSX here!</div>
);
});
If you just have to render JSX, do this:
array.map(a => (
<div>JSX here!</div>
));
Since => () is implicitly returning the stuff between ().
In arrow functions curly brackets are used for closures. So it will wrap your function.
If you use arrow function with curly brackets, you have to use return. Like this:
screenshots.map(screenshot => {
console.log('I can do whatever I like here...');
return 'but I have to return something!'
});
Arrow function without curly brackets automatically returns your statement and it has to be used only with one statement.
screenshots.map(screenshot =>
'It returns this string without using word `return`!'
);
Your code should look like this (with curly brackets and return):
{screenshots && screenshots.length && screenshots.map(screenshot => {
console.log('Wow! I am in arrow function! I have to return something.');
return
<div className="container img--container" key={screenshot.id}>
<SVG className="icon remove--icon" src={removeCircle}/>
<img src={screenshot.image} title={"screenshot"} className="p-absolute"/>
</div>
})}
or you can just delete curly brackets like this:
{screenshots && screenshots.length && screenshots.map(screenshot =>
<div className="container img--container" key={screenshot.id}>
<SVG className="icon remove--icon" src={removeCircle}/>
<img src={screenshot.image} title={"screenshot"} className="p-absolute"/>
</div>
)}
You can read more about arrow functions at w3schools.
I've been working through react examples, and I've been hacking away building some components. Now I feel i'm running into a fundamental "Brain Fart", regarding component structure and nesting.
What I'm after:
Input component with Optional Labels and help text.
What I have right now: ( which does work )
Input.js
//...//
var MyInput = React.createClass( {
render: function() {
//...//
var helpText = null;
if( typeof this.props.helpText !== 'undefined' ){
helpText = <p className="help-block" > {this.props.helpText} </p>;
}
return (
<div className={ className }>
<MyLabel showLabel={ this.props.showLabel} htmlFor={ this.props.name }>
{ this.props.title }
</MyLabel>
<input
type={ this.props.type || 'text' }
name={ this.props.name }
onChange={ this.changeValue }
value={ this.getValue() }
checked={ this.props.type === 'checkbox' && this.getValue() ? 'checked' : null }
placeholder={ this.props.title }
/>
<span className='validation-error'>{ errorMessage }</span>
{helpText}
</div>
);
}
});
module.exports = MyInput;
LoginForm.js
//...//
var LoginForm = React.createClass({
// ... //
render: function() {
return (
<Form className=" col-sm-11 col-lg-10 block-center loginFrm" >
<div className="row">
<FrmInput value =""
name="username"
title="Username"
className="col-sm-5"
showLabel={false}
helpText= { <span> Help text with link </span>}
required />
<FrmInput value =""
type="password"
name="password"
title="Password"
className="col-sm-5"
showLabel={false}
required />
<button type="submit"
className="btn btn-default input-sm "
>
Sign In
</button>
</div>
<div className="row">
<div className="pull-right" >
<FrmCheckbox name="rememberMe"
title="Remember Me"
/>
</div>
</div>
</Form>
);
},
});
module.exports = LoginForm;
Making the label optional was easy. I use a BOOL showLabel property on the <MyInput/> component and pass that into the MyLabel component. showLabel is assumed TRUE, so the label is shown unless you set showLabel to false as seen above ( then <MyLabel/> just returns NULL ).
I first tried a similar method with a <help/> component to add the optional help text after the input inside <MyInput/>. Everything worked until I added a link inside the help text. Researching I found dangerouslySetInnerHTML as a means to pass HTML content into a component. While testing I also found the code above appears to work also, though I'm not exactly sold on why and how "good" this approach is.
In short it appears I'm just passing JSX objects into my component for rendering. inside <Form> (from LoginForm.js ) on the <FrmInput/> component there is a property named helpText set as follows
helpText= { <span> Help text with link </span> }
inside the <MyInput/> component I'm testing/listening for the helpText property and setting it to a variable when found (Again wrapping with JSX)
var helpText = null;
if( typeof this.props.helpText !== 'undefined' ){
helpText = <p className="help-block" > {this.props.helpText} </p>;
}
Then in the Render Method I have { helpText }
All in all it looks like I'm just passing javascript objects ( via JSX ) on through untill the final render method. I have not seen the above used in tutorials or documentation, so I'm just looking for a professional opinion.
Is the above "good" practice or how could this better be handled.
There's nothing 'wrong' with your approach. A few suggestions that can help stream line a bit.
You can shorten this block to a simple inline ternary:
var helpText = null;
if( typeof this.props.helpText !== 'undefined' ){
helpText = <p className="help-block" > {this.props.helpText} </p>;
}
You can remove the above and in your render replace {helpText} with:
{ this.props.helpText ? this.props.helpText : null }
In form input remove the inline helpText html and move to a variable using parens for the JSX.
const helpTextContent = ( <span> Help text with link </span> );
Then inline: helpText = { helpTextContent }
Lastly if you're using ES6 you can use the following syntax to make using props less cumbersome:
let { helpText, someOtherProp, anotherProp } = this.props;
Then you can just refer to helpText or someOtherProp directly without the this.prop every time.
Hope that helps!