I have the following React component:
class Parent extends Component {
constructor(props) {
super(props)
this.state = {
isRendered: false
}
}
render() {
return (
<div className="result">
Rendering result
</div>
)
}
}
Based on the state of this.state.isRendered, I want my <div> component to render if the state is true, and not render if the state is false.
What would be the best way to organize it in React?
Just check this.state.isRendered in the render. Here I used a simple AND check. Click on the button to change state and see how it works (snippet takes a short while to run):
class Parent extends React.Component {
constructor(props) {
super(props)
this.state = {
isRendered: false
}
}
render() {
const {
isRendered
} = this.state;
return (
<div>
{isRendered &&
<div className="result">
Rendering result
</div>
}
<button onClick={() => {this.setState({isRendered: !isRendered})}}>{isRendered? 'Hide' : 'Show'}</button>
</div>
)
}
}
ReactDOM.render(<Parent />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Using a ternary operator check whether isRendered is true else return null:
class Parent extends Component {
constructor(props) {
super(props)
this.state = {
isRendered: false
}
}
render() {
return (
<div>
{this.state.isRendered ?
<div className="result">
Rendering result
</div> : null
}
</div>
)
}
}
You are allowed to return null or false for React components. So, if you don't want anything to get rendered, you could do the following:
...
render() {
if (!this.state.isRendered) return null
return (
<div className="result">
Rendering result
</div>
)
}
or, alternatively
...
render() {
return this.state.isRendered && (
<div className="result">
Rendering result
</div>
)
}
You can use simple conditional ternary operator to do this:
condition ? if_true_result : if_false_result
Your code should be like this:
render() {
const {isRendered} = this.state;
return isRendered ?
<div className="result">
Rendering result
</div>
: ''
}
Another official way is following the guidelines about Conditional Rendering in Reactjs document: https://reactjs.org/docs/conditional-rendering.html
There are many ways to accomplish that
{ this.state.isRendered ?
<div className="result">
This if the isRendered is true
</div>
: <div className="result">
This if the isRendered is false
</div> }
Related
I'm trying to fetch an api of quotes and populate the react component with the first one. Later I'll use the button to pick a random one. I'm just now learning react, my react tutorial in freecodecamp didn't show anything about fetch so I found the code to pull these quotes online. If I add another callback after the this.setState I can console.log and see all the arrays but even with the if statement in the render it doesn't seem to be there in the state to render. What am I missing about setting the state or getting the component to render after the state has set to the array. I have already looked at this stackoverflow question.
class Quotes extends React.Component{
constructor(props){
super(props)
this.state = {
quotes: []
}
}
componentDidMount() {
fetch("https://type.fit/api/quotes")
.then((response) => response.json())
.then(quotesList => {
this.setState({ quotes: quotesList });
});
}
render(){
if (!this.state.quotes) {
return <div />
}
return(
<div>
<p id="text">{this.state.quotes[0].text}</p>
<p id="author">{this.state.quotes[0].author}</p>
<div id="buttons">
<button id="new-quote">New Quote</button>
<a id="tweet-quote" href="#"><i className="fa-brands fa-twitter"></i></a>
</div>
</div>
);
}
}
class QuoteBox extends React.Component{
constructor(props){
super(props)
}
render(){
return(
<div id="quote-box">
<Quotes />
</div>
);
}
}
ReactDOM.render(<QuoteBox />, document.getElementById('page-wrapper'))
#page-wrapper{
#quote-box{
display:flex;
height:100vh;
justify-content:center;
align-items:center;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="page-wrapper">
</div>
An empty array [] is not a falsy value, consequently your if does not get triggered and an out of bounds array access is done. Check for array length in your if instead and it will work.
See this thread on StackOverflow which covers truthy and falsy values.
Here your code with the condition within the if changed to
this.state.quotes.length === 0.
class Quotes extends React.Component {
constructor(props) {
super(props);
this.state = {
quotes: [],
};
}
componentDidMount() {
fetch("https://type.fit/api/quotes")
.then((response) => response.json())
.then((quotesList) => {
this.setState({ quotes: quotesList });
});
}
render() {
// check for array length here
if (this.state.quotes.length === 0) {
return <div>Fetching data...</div>;
}
return (
<div>
<p id="text">{this.state.quotes[0].text}</p>
<p id="author">{this.state.quotes[0].author}</p>
<div id="buttons">
<button id="new-quote">New Quote</button>
<a id="tweet-quote" href="#">
<i className="fa-brands fa-twitter"></i>
</a>
</div>
</div>
);
}
}
class QuoteBox extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div id="quote-box">
<Quotes />
</div>
);
}
}
ReactDOM.render(<QuoteBox />, document.getElementById("page-wrapper"));
#page-wrapper{
#quote-box{
display:flex;
height:100vh;
justify-content:center;
align-items:center;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="page-wrapper">
</div>
class Main extends Component{
/*Skip function and constructor...*/
var previewContainer = this.refs.localMedia;
previewContainer.appendChild("<div>Test</div>");
/*Skip some code...*/
render() {
return (
<div className="container my-4">
<div className="row">
<div className="col">
<div>Screen section</div>
<div className="screen_section">
{this.state.showMyScreen ? <MyScreen localMediaAvailable={this.state.localMediaAvailable} /> : null }
</div>
</div>
</div>
</div>
)
}
}
class MyScreen extends Component {
constructor(props) {
super(props)
}
render() {
let showLocalTrack = this.props.localMediaAvailable ? (
<div className="flex-item"><div ref="localMedia" style={{height:320, width:640}} /> </div>) : '';
return (
<div>
<div>My Screen</div>
{showLocalTrack}
</div>
)
}
}
I write some react code as above, and I have an error message of fail to appendChild of undefined, the problem is I cannot refer the variable with var previewContainer = this.refs.localMedia;
Is it possible to have any method to solve this problem? Or instead of serate them into two component, I should write them in one instead?
How to return element in react class functions on a click. is it even possible?
class Item extends Component {
constructor(props) {
super(props);
this.itemInfo = this.itemInfo.bind(this);
}
itemInfo = () =>{
return <div> some info</div>
}
render(){
return(
<div>
<div onClick={this.itemInfo}> Click Here <div>
</div>
)
}
}
class Item extends React.Component {
state = {
showDiv: false
};
render() {
return (
<div>
<div
style={{ cursor: "pointer" }}
onClick={() =>
this.setState(prevState => ({
showDiv: !prevState.showDiv
}))
}
>
Click Me
</div>
{/*Show the INFO DIV ONLY IF THE REQUIRED STATE IS TRUE*/}
{this.state.showDiv && <InfoDiv />}
</div>
);
}
}
//This is the div which we want on click
var InfoDiv = () => (
<div style={{ border: "2px solid blue",borderRadius:10, padding: 20 }}>
<p> Long Text DIVLong Text DIVLong Text DIVLong Text DIVLong Text DIV </p>
</div>
);
ReactDOM.render(<Item />, document.getElementById("root"));
<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="root"></div>
You should do that in the state.
itemInfo = () =>{
this.setState({ component:<div> some info</div> });
}
and render the component like this
return(
<div>
<div onClick={this.itemInfo}> Click Here <div>
{this.state.component}
</div>
)
You can try something like this, using the state and conditional rendering:
class Item extends Component {
constructor(props) {
super(props)
this.state = {
showMore: false,
}
}
toggleShowMore = () => {
this.setState({ showMore: !this.state.showMore })
}
render() {
return (
<div>
<div onClick={this.toggleShowMore}>
{this.state.showMore ? 'Show less' : 'Show more'}
</div>
{this.state.showMore ? <div>some info</div> : null}
</div>
)
}
}
Here's how I would do it:
function ItemInfo() {
return(
<div>Some Info</div>
);
}
class Item extends Component {
constructor(props) {
super(props);
this.handleClick= this.handleClick.bind(this);
this.state = {
showInfo: false
}
}
handleClick() {
this.setState((prevState) => {showInfo: !prevState.showInfo});
}
render(){
return(
<div>
<div onClick={this.handleClick}> Click Here <div>
{ this.state.showInfo ?
<ItemInfo/>
: null }
</div>
)
}
}
showing the same state,but i want display indiviual state.when i click the hospital its not showing hospital component but both hospital,fireservice showing same state.click function worked but not showing the indiviual component only showing same component
import React, { Component } from 'react';
import './importantplaces.css';
import Showhospital from './Hospitallist/Showhospital';
import Showfireservice from './Fireservice/Showfireservice';
export default class Importantplaces extends Component {
constructor() {
super();
this.state = {
showHospital: false,
showFire: false
}
}
onClick(e) {
e.preventDefault();
this.setState({ showHospital: !this.state.showHospital })
this.setState({ showFire: !this.state.showFire })
}
render() {
return (
<div className="Importantplaces">
<div className="placelist">
<div className="container-fluid">
<div className="row">
<div className="col-md-6">
<a onClick={this.onClick.bind(this)} className="place-content p-btn mb-70">Hospital</a>
<a onClick={this.onClick.bind(this)} className="place-content p-btn mb-70">Fire Service</a>
</div>
<div className="col-md-6">
<a onClick={this.onClick.bind(this)} className="place-content p-btn mb-70">Police Station</a>
<a onClick={this.onClick.bind(this)} className="place-content p-btn mb-70">Post Office</a>
</div>
</div>
</div>
</div>
{this.state.showHospital && <Showhospital />}
{this.state.showFire && <Showfireservice />}
</div>
);
}
}
Please check below code you can use one function to onclick
class B extends React.Component {
render(){
return(
<div>
<h1>BBBB</h1>
</div>
);
}
}
class C extends React.Component {
render(){
return(
<div>
<h1>CCCC</h1>
</div>
);
}
}
class A extends React.Component {
constructor() {
super();
this.state = {
showB: false,
showC: false,
}
this.handleMultiSelect = this.handleMultiSelect.bind(this);
}
handleMultiSelect(val) {
console.log('aaaa', val);
if(val === 'b'){
this.setState({
showB: !this.state.showB
});
} else if(val === 'c'){
this.setState({
showC: !this.state.showC
});
}
}
render() {
return (
<div>
<a onClick={() => {this.handleMultiSelect('b')}}>B</a>
<br />
<a onClick={() => {this.handleMultiSelect('c')}}>C</a>
{this.state.showB && <B/>}
{this.state.showC && <C/>}
</div>
);
}
}
ReactDOM.render( < A / > , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
Right now you are changing both your state on the click event. So they both always go from false to true and back to false.
You have different way to solve this : adding an argument to your onclick function to define which state should go to true, or making different onClick function for each component you want to show. Second solution would go as such :
<a onClick={this.onHospitalClick.bind(this)} className="place-content p-btn mb-70">Hospital</a>
<a onClick={this.onFireServiceClick.bind(this)} className="place-content p-btn mb-70">Fire Service</a>
and having these two functions instead :
onHospitalClick(e) {
e.preventDefault();
this.setState({ showHospital: true, showFire : false })
}
onFireServiceClick(e) {
e.preventDefault();
this.setState({ showHospital: false, showFire : true })
}
I have a react element like this:
import React, { PropTypes, Component } from 'react'
class AlbumList extends Component {
constructor(props) {
super(props);
this.state = {'active': false, 'class': 'album'};
}
handleClick() {
if(this.state.active){
this.setState({'active': false,'class': 'album'})
}else{
this.setState({'active': true,'class': 'active'})
}
}
render() {
var album_list
const {user} = this.props
if(user.data){
list = user.data.filter(album => album.photos).map((album => {
return <div className={"col-sm-3"} key={album.id}>
<div className={this.state.class} key={album.id} onClick={this.handleClick.bind(this)}>
<div className={"panel-heading"}>{ album.name }</div>
<div className={"panel-body"}>
<img className={"img-responsive"} src={album.photo.source} />
</div>
</div>
</div>
}))
}
return (
<div className={"container"}>
<div className="row">
{list}
</div>
</div>
)
}
}
export default AlbumList
Here map gives the list of filter data as I wanted. Here what I am doing changes the class of all the list element if I click on one.
I am getting the class name from this.state.class
How can I change the class of only element that i have clicked..
Thanks in advance ...
I have considered it once.So you have so many divs and you want to know which is clicked.My way to solve this problem is to give a param to the function handleClick and you can get the dom of the div while you click the div.Like this:
array.map(function(album,index){
return <div onClick={this.handleClick}/>
})
handleClick(e){
console.log(e.target);
e.target.className = 'active';
...
}
Then you have a param for this function.While you can use the e.target to get the dom of your div which is clicked.
There are some mistake into your code about the state.class.
class AlbumList extends Component {
constructor(props) {
super(props);
this.state = {'active': false, 'class': 'album'};
}
handleClick(e) {
if(e.target.class === 'active'){
e.target.className = 'album'
}else{
e.target.className = 'active'
}
}
render() {
var album_list
const {user} = this.props
if(user.data){
list = user.data.filter(album => album.photos).map((album => {
return (
<div className={"col-sm-3"} key={album.id}>
<div className='active' key={album.id} onClick={this.handleClick.bind(this)}>
<div className={"panel-heading"}>{ album.name }</div>
<div className={"panel-body"}>
<img className={"img-responsive"} src={album.photo.source} />
</div>
</div>
</div>
)
}))
}
return (
<div className={"container"}>
<div className="row">
{list}
</div>
</div>
)
}
}
You can try this and tell me anything wrong.