How to return element in react class functions - reactjs

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>
)
}
}

Related

Close div in all child components

What i am trying to do is this: i have multiple child components,
when i click on details i want to hide the same div in other child components
for example
when i click on div 1 close 2 and 3 and so on
<div onClick="showDetails()">component 1</div>
<div onClick="showDetails()">component 2</div>
<div onClick="showDetails()">component 3</div>
<details></details>
I have tried using ref, but ref did not work it only closes the first component div..
export default class Parent extends Component {
constructor(props) {
super(props)
this.myRef = React.createRef();
this.handleActivity = this.handleActivity.bind(this)
}
handleActivity() {
//call to a method in Child component
this.myRef.current.closeAll()
}
render() {
return (
<div>
<Child ref={this.myRef} closeAllOather={this.handleActivity} />
<Child ref={this.myRef} closeAllOather={this.handleActivity} />
<Child ref={this.myRef} closeAllOather={this.handleActivity} />
<Child ref={this.myRef} closeAllOather={this.handleActivity} />
</div>
)
}
}
export default class Child extends Component {
constructor(props) {
super(props)
this.state = {
show: false,
}
this.show = this.show.bind(this)
this.hide = this.hide.bind(this)
}
closeAll(){
this.setState({show: false})
}
show() {
this.props.closeAllOather()
this.setState({ show: true })
}
hide() {
this.setState({ show: false })
}
render() {
return (
<div>
<div onClick={this.show} />
<div style={this.state.show ? visible : hidden}>
<div style={detailBlock}>
<span style={{ float: 'right' }} onClick={this.hide}>
close
</span>
{this.props.text}
<br />
</div>
</div>
</div>
)
}
}
Any suggestion on how this can be done?
I would keep the currentElement in Parent and verify in Child if it's active.
Example:
class Parent extends React.Component {
constructor(props) {
super(props)
this.state = {
activeElement: null
};
this.onChildClick = this.onChildClick.bind(this)
}
onChildClick(e) {
this.setState({activeElement: e.currentTarget});
}
render() {
return (
<div>
<Child onClick={this.onChildClick} activeElement={this.state.activeElement} />
<Child onClick={this.onChildClick} activeElement={this.state.activeElement} />
<Child onClick={this.onChildClick} activeElement={this.state.activeElement} />
<Child onClick={this.onChildClick} activeElement={this.state.activeElement} />
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
const isActive = this.myRef.current && this.myRef.current === this.props.activeElement;
return (
<div ref={this.myRef} style={{color: isActive ? 'red' : 'black'}} onClick={this.props.onClick}>Child</div>
)
}
}
https://jsfiddle.net/n7y9buqg/5/
Change handleActivity in the Parent to
handleActivity(id) {
this.setState({
selectedChild:id
});
}
and the render in the parent to
render() {
return (
<div>
<Child isSelected={this.state.selectedChild === 1 ? "true":"false"} ref={this.myRef} closeAllOather={this.handleActivity(1)} />
<Child isSelected={this.state.selectedChild === 2 ? "true":"false"} ref={this.myRef} closeAllOather={this.handleActivity(2)} />
<Child ref={this.myRef} isSelected={this.state.selectedChild === 3 ? "true":"false"} closeAllOather={this.handleActivity(3)} />
<Child ref={this.myRef} isSelected={this.state.selectedChild === 4 ? "true":"false"} closeAllOather={this.handleActivity(4)} />
</div>
)
}
Finally in the child do:
render() {
return (
<div>
<div onClick={this.show} />
<div style={this.state.show ? visible : hidden}>
<div style={this.props.isSelected === "true" ? detailBlock:{display: "none"}}>
<span style={{ float: 'right' }} onClick={this.hide}>
close
</span>
{this.props.text}
<br />
</div>
</div>
</div>
)
}

Does not showing indiviual state in react js?

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 })
}

onClick event on an array element javascript React

I need to do a collapsible section with a list of disciplines. The disciplines are stored in an array. I wrote an onClick event but except one discipline which I clicked, I get all of them slid down. How can I apply the event to each element, so I can decide which one will be slide down?
export default class Predictions extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
this.state={
display: 'block',
};
}
handleClick(e) {
this.setState({
display: this.state.display === 'none' ? 'block' : 'none',
});
console.log('click', e);
};
render() {
return (
<section className="l-section c-predictions" >
<h2 className="header" >Predictions</h2>
<div className="content">
{this.props.disciplines.map((discipline, index) => {
return (
<div onClick={event => this.handleClick(discipline.id, event)} key={discipline.name} className="c-discipline">
<span className="name">{discipline.name}</span> - <span className="score">{disciplineScore(this.props.athlete.skillset, discipline.requirements)}</span>
<div style={this.state} className="element">
<p>{discipline.tags !== undefined ? discipline.tags.toString().replace(',', ', ') : ''}</p>
<p className="isIndividual">{discipline.isIndividual===true ? "Individual sport" : "Team sport"}</p>
<img src={discipline.photo}/>
</div>
</div>
)
})}
</div>
</section>
)
}
}
You need a way to identify which element has been clicked.
Here's an example:
export default class App extends React.Component {
state = {
opened: true,
selected: ''
};
toggleHidden = key => {
this.setState({ opened: !this.state.opened, selected: key });
};
render() {
return (
<div>
{arr.map((s, i) => (
<div key={i}>
<p>{s}</p>
<button onClick={() => this.toggleHidden(i)}>Toggle</button>
{!this.state.opened && this.state.selected === i && <h1>{s}</h1>}
</div>
))}
</div>
);
}
}

Unable to invoke props function passed to children in a loop reactjs

I am new to react. I am just trying to create a comment box and comment board which contain multiple comments.
Each comments have one inputbox, button(save,edit) and button(remove). I have passed function made in board named updateComment to Component Comment as props.
Now When I am trying to execute save of child function in which I have called parent function updateComment using this.props.updateComment
it is giving me error can't read property of undefined.
I have searched for similar question on stackoverflow but I am unable to solved this proplem.
My app.js code is as below.
import React from 'react';
import { Home } from './home.jsx';
class App extends React.Component {
render() {
return (
<div>
<Header/>
<Board />
</div>
);
}
}
class Header extends React.Component {
render() {
return (
<div>
<h1>Header</h1>
</div>
);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
comments:[
"My name is brijesh",
"My name is santosh",
"My name is manoj"
]}
};
removeComment(i) {
console.log("going to remove element i",i);
var arr = this.state.comments;
arr.splice(i,1);
this.setState({comments:arr});
};
updateComment(newComment, i) {
var arr = this.state.comments;
arr[i] = newComment;
this.setState({comments:arr});
};
render() {
return (
<div className="board">
{
this.state.comments.map(function(text,i) {
return (
<Comment key ={i} index = {i}
updateComment={() => {this.updateComment}}
removeComment={() => {this.removeComment}}>
{text}
</Comment>
)
})
}
</div>
)
}
}
class Comment extends React.Component {
constructor(props) {
super(props);
this.state = {
edit: false
};
};
edit(){
this.setState({edit:true});
console.log("you clickced on edit0");
};
save(){
this.setState({edit:false});
var newText = this.refs.newText.value;
this.props.updateComment(newText, this.props.index);
console.log("you clickced on edit0",newText);
};
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
if(this.state.edit) {
return (
<div>
<div className="comment">
<input type="text" ref="newText" defaultValue={this.props.children} onChange={ this.handleChange.bind(this) } />
<button onClick={this.save.bind(this)}>Save</button>
</div>
</div>
)
}
else {
return (
<div>
<div className="comment">
<div>{ this.props.children }</div>
<button onClick={this.edit.bind(this)}>Edit</button>
</div>
</div>
)
}
}
}
export default App
And my main.js looks like this.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(
( < App / > ), document.getElementById('app'));
I have also created fiddle also.
https://jsfiddle.net/aubrijesh/k3h2pcnj/#&togetherjs=uEI7TFnJD1
I believe that DOMZE is on the right track but you should also bind the function in the map statement. In my opinion arrow functions makes it much easier to keep track of what this refers to.
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
comments:[
"My name is brijesh",
"My name is santosh",
"My name is manoj"
]}
};
removeCommment(i) {
console.log("going to remove element i",i);
var arr = this.state.comments;
arr.splice(i,1);
this.setState({comments:arr});
};
updateComment(newComment, i) {
var arr = this.state.comments;
console.log("new Comment");
arr[i] = newComment;
this.setState({comments:arr});
};
render() {
return (
<div className="board">
{
this.state.comments.map((text,i) => {
return (
<Comment key ={i} index = {i}
updateComment={() => {this.updateComment}}
removeComment={() => {this.removeComment}}>
{text}
</Comment>
)
})
}
</div>
)
}
}
class Comment extends React.Component {
constructor(props) {
super(props);
this.state = {
edit: false
};
};
edit(){
this.setState({edit:true});
console.log("you clickced on edit0");
};
save(){
this.setState({edit:false});
var newText = this.refs.newText.value;
this.props.updateComment(newText, this.props.index);
console.log("you clickced on edit0",newText);
};
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
if(this.state.edit) {
return (
<div>
<div className="comment">
<input type="text" ref="newText" defaultValue={this.props.children} onChange={ this.handleChange} />
<button onClick={this.save.bind(this)}>Save</button>
</div>
</div>
)
}
else {
return (
<div>
<div className="comment">
<div>{ this.props.children }</div>
<button onClick={this.edit.bind(this)}>Edit</button>
</div>
</div>
)
}
}
}
ReactDOM.render(<Board />, 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>
update your render method
let self = this;
return (
<div className="board">
{
self.state.comments.map(function(text,i) {
return (
<Comment key ={i} index = {i}
updateComment={() => {self.updateComment}}
removeComment={() => {self.removeComment}}>
{text}
</Comment>
)
})
}
</div>
)
You need to bind the class to the function, so that it knows what "this" is
render() {
return (
<div className="board">
{
this.state.comments.map(function(text,i) {
return (
<Comment key ={i} index = {i}
updateComment={this.updateComment.bind(this)}
removeComment={this.removeComment.bind(this)}>
{text}
</Comment>
)
})
}
</div>
)
}
Note that you may want to do those bindings in the constructor so that it doesn't bind at each and every render

react change the class of list item on click

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.

Resources