What is the equivalent to ng-if in react.js?
ReactjsReactjs Problem Overview
I'm coming to react from using angular and I'm trying to figure out a good react alternative to angular's ng-if directive where I render or dont render an element based on a condition. Take this code for example. I'm using typescript (tsx) btw but that shouldn't matter much.
"use strict";
import * as React from 'react';
interface MyProps {showMe: Boolean}
interface MyState {}
class Button extends React.Component <MyProps, MyState>{
constructor(props){
super(props);
this.state = {};
}
render(){
let button;
if (this.props.showMe === true){
button = (
<button type="submit" className="btn nav-btn-red">SIGN UP</button>
)
} else {
button = null;
}
return button;
}
}
export default Button;
This solution works, but is there another way that's generally used to achieve this effect? I'm just sort of guessing
Reactjs Solutions
Solution 1 - Reactjs
How about ternary operator?
render() {
return (
this.props.showMe ? <button type="submit" className="btn nav-btn-red">SIGN UP</button> : null
);
}
You can also use &&
:
render() {
return (
this.props.showMe && <button type="submit" className="btn nav-btn-red">SIGN UP</button>
);
}
Large block as in the comment can easily be handled by wrapping the JSX in ()
s:
render() {
return this.props.showMe && (
<div className="container">
<button type="submit" className="btn nav-btn-red">
SIGN UP
</button>
</div>
);
}
Also inline:
render() {
return (
<div className="container">
{this.props.showMe && <button type="submit" className="btn nav-btn-red">SIGN UP</button>}
</div>
);
}
Solution 2 - Reactjs
I am leaving this here for historical purposes, please see my edits below for a much better solution after having developed in react for a while
I ended up creating an NgIf component (this is react native but probably works for react)
Code:
import React, {Component} from "react";
class NgIf extends Component {
render() {
if (this.props.show) {
return (
this.props.children
);
} else {
return null
}
}
}
export default NgIf;
Usage:
...
import NgIf from "./path/to/component"
...
class MyClass {
render(){
<NgIf show={this.props.show}><Text>This Gets Displayed</Text></NgIf>
}
}
Im new to this so can probably be improved upon, but helps me in my transition from Angular
EDIT
See edits below for a better explanation once I had more experience
Thanks to Jay's Comment below, a great idea is also:
render() {
<View>{this.props.value ? <Text>Yes</Text> : <Text>No</Text>}</View>
}
OR
render() {
<View>{this.props.value && <Text>Yes</Text>}</View>
}
Similar to some of the other answers but works inline, instead of using the entire render block / function, doesn't require a special component, and you can use an else statement with the ternary operator. Plus items contained within the if statement don't throw an error if their parent object doesn't exist. Ie if if props.value
doesn't exist, then props.value.value2
won't throw an error.
See this answer https://stackoverflow.com/a/26152067
EDIT 2:
As per the above link (https://stackoverflow.com/a/26152067) and after a lot more experience developing react apps, the above way it not the best way to do things.
Conditional operators in react are actually very easy to get your head around. There are two ways to do things:
//Show if someItem
{someItem && displayThis}
//Show if else
{someItem ? displayThisIfTrue : displayThisIfFalse}
One caveat you might hit is if "someItem" isn't a boolean expression. If it is say 0 react will print a 0 or react native will give you an error about needing to wrap "0" in a text element. This usually isn't a problem for falsy tests, but will present an issue for truthy tests. For example:
{!someItem && displayThis} //Will work just fine if item is 0 or null or "" etc
{someItem && displayThis} //Will print the value of someItem if its not falsy
My often used trick? double negatives.
{!!someItem && displayThis}
Note that this does not apply to ternary operators (myVar ? true : false) since it implicitly converts the result into a boolean expression.
Solution 3 - Reactjs
If you have other elements too you can wrap just the conditional like so:
render() {
return (
<div>Stuff</div>
{this.props.showMe && (
<button type="submit" className="btn nav-btn-red">SIGN UP</button>
)}
<div>More stuff</div>
);
}
Solution 4 - Reactjs
I just wanted to add that *ngIf
in angular does not instantiate the component that it is attached to. In React if you use an if statement within the return
statement then it will still instantiate the component even though it isn't displayed. To achieve a true *ngIf
type behavior in React you have to create a variable that holds the conditional component outside of the return
statement:
render() {
const show = false
return show
? <AwesomeComponent /> //still instantiated
: null
}
render() {
let c = null
const show = false
if (show) {
c = <AwesomeComponent /> //not instantiated
}
return c
}
Solution 5 - Reactjs
A bit nicer:
render() {
return (
this.props.showMe && <button type="submit" className="btn nav-btn-red">SIGN UP</button>
);
}
Solution 6 - Reactjs
I can think of at least three different ways to simulate ng-if functionality in React
- if
- switch
- IIFE (immediately-invoked function expression)
You can read the post here: Angular's ng-if Equivalent In a React Component
Basically, you want to do something like this:
var IfDemoComponent = React.createClass({
render: function() {
var el = null;
if (this.props.showMe) {
el = (
<div>
I am only included in the DOM if this.props.showMe evaluates to true.
</div>
);
}
return el;
}
});
Solution 7 - Reactjs
> false
, null
, undefined
, and true
are valid children. They simply don’t
> render. These JSX expressions will all render to the same thing:
So you can try this
const conditional=({condition,someArray})=>{
return(
<div>
{condition && <Header /> // condition being boolean}
{someArray.length>0 && <Content />}
</div>
)
}
this can be useful to conditionally render React elements. This JSX only renders a
Solution 8 - Reactjs
I do not like having many ternary operators in the code. That's why I made a library with a couple of useful components. "RcIf"
<RcIf if={condition} >
<h1>I no longer miss ngif</h1>
</RcIf>
<RcIf if={othercondition} >
<h1>I no longer miss v-if</h1>
<RcElse>
<h1>I love react</h1>
</RcElse>
</RcIf>
You can install it from npm
Solution 9 - Reactjs
I am the creator of the Tersus-jsx.macro and I think this module provides exactly what is needed for this question.
Rather than mixing JSX expressions and ES6 to achieve ng-if or ng-repeat, this macro allows doing things the same way as in AngularJS for React JSX, e.g. for ng-if:
<div>
<button
tj-if={a === 0}
id="gotoA"
className="link"
onClick={clicking}
/>
</div>
which is equivalent to
<div>
{(a === 0) && (
<button
id="gotoA"
className="link"
onClick={clicking}
/>
)}
</div>
Given that the latest version of create-react-app support Babel-Macro out of the box, all you need to do is npm install this module, wrap the render return with "tersus" and start assigning those props.
You can install this from: https://www.npmjs.com/package/tersus-jsx.macro
Solution 10 - Reactjs
I'm coming from an angular background as well and was looking for a simple one liner to show the tag if the variable had any elements. This worked for me:
<div className="comic_creators">
{c.creators.available > 0 ? <h4>Creators</h4> : null }
{c.creators.items.map((creator,key) =>
<Creator creator={creator} key={key}></Creator>
)}
</div>
Solution 11 - Reactjs
From React Documentation
https://reactjs.org/docs/conditional-rendering.html
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('root')
);
Solution 12 - Reactjs
Personally I like using getters, it's clean and assure reactivity :
get toBeDisplayed(){
const { someLogicState } = this.state;
if(someLogicState)
return (
<div>
Hi, world !
</div>
);
else
return null;
}
render(){
return (<div>{this.toBeDisplayed}</div>);
}
Solution 13 - Reactjs
I just create a method to take exprestion and two another arguments as the template in case the expression truth and the other is an option else template
export function rif(exp, template, elseTemplate = null) {
if (exp) {
return template;
} else {
return elseTemplate;
}
}
and I use it like this
import { rif } from '../utilities';
...
render() {
return (
<main role="main" className="container">
{rif(
this.movies.length > 0,
<p>Showing {this.movies.length} movies. </p>,
<p>There are no movies..</p>
)}
</main>
);
}
Solution 14 - Reactjs
I am working both angular and react. I think angular
nicely manage logical condition through different directives.
In reactjs
this approach work different way.
You can use if else
condition as return
of render function
or ternary operator
.
> With if else
render(){
const auth = true;
if(!auth)
return(
<div className="ps-checkout__login">
<div className="d-flex flex-row">
<div className="p-2"><img src="../../../static/img/return-customer.png"></img>
Returning Customer?</div>
<div className="p-2">
<Link href="/account/login">
<a>
Click here to login
</a>
</Link>
</div>
</div>
</div>
)
else return null;
}
> With ternary operator
{ auth?
(<div className="ps-checkout__login">
<div className="d-flex flex-row">
<div className="p-2"><img src="../../../static/img/return-customer.png"></img>
Returning Customer?</div>
<div className="p-2">
<Link href="/account/login">
<a>
Click here to login
</a>
</Link>
</div>
</div>
</div>):null }