Does not showing indiviual state in react js? - reactjs

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

Related

React state doesn't seem to be fetching api and setting state before render

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>

How to return element in react class functions

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

error while using state and map in reactjs

I am new to react. I am fetching github user info on search. I unable
to fetch data in my child component. this is my code below.
whats the problem , cant i use this.state.userList.map
class SearchHeader extends Component {
constructor(props) {
super(props);
this.state = {
errorMessage: '',
userList: [],
isOpen: false,
userName:''
};
this.toggle = this.toggle.bind(this);
this.getUsers = this.getUsers.bind(this);
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
// componentWillMount(){
// this.getUsers();
// }
getUsers(e) {
console.log('get users called='+e.target.value);
fetch('https://api.github.com/search/users?q='+ e.target.value)
.then(res => res.json())
.then(
userList =>{
this.setState({userList: userList})
console.log(userList);
}
);
}
render() {
return (
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-primary navbar-inner">
<div className="collapse navbar-collapse navbar-inner navb" >
<ul className="navbar-nav bg-light mr-auto">
<li className="nav-item dropdown">
<a className="nav-link dropdown-toggle auto" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Sort
</a>
<div className="dropdown-menu" aria-labelledby="navbarDropdown">
<a className="dropdown-item" href="#">Sort by Name (ascending)</a>
<a className="dropdown-item" href="#">Sort by Name (descending)</a>
<div className="dropdown-divider"></div>
<a className="dropdown-item" href="#">Sort by Rank (ascending)</a>
<a className="dropdown-item" href="#">Sort by Rank (descending)</a>
</div>
</li>
</ul>
<form className="form-inline my-2 my-lg-0 auto" onSubmit={this.getUsers}>
<div className="form-group">
<input className="form-control mr-sm-2" type="Search" placeholder="Search"
aria-label="Search"
id="userName"
onKeyUp={this.getUsers} >
</input>
</div>
</form>
</div>
</nav>
<div >
<UserList userList={this.state.userList}/>
</div>
</div>
);
}
}
export default SearchHeader;
This is my child component below where I am fetching data from parent
component
This is my child component below where I am fetching data from parent
component
class UserList extends Component {
constructor(props) {
super(props)
this.state ={
users:this.props.userList
}
}
render() {
return (
<div className="container-fluid">
<br />
{
this.state.users.map((user)=>
<div className="jumbotron container">
{user.login}
</div>
)
}
</div>
);
}
}
export default UserList;
You have several problems in your components:
do not copy parent's state into chilren states: users:this.props.userList. Use this.props directly instead and React will know it must re-render children
do not rely on current state to set new state. Use function with prevState instead of isOpen: !this.state.isOpen.
make a copy of event's value before passing it to setState like this const {value} = e.target;
assign unique key to each user in your list (not indexes!), or it won't re-render correctly on list update
So your code would look like this:
class SearchHeader extends Component {
constructor(props) {
super(props);
this.state = {
errorMessage: '',
userList: [],
isOpen: false,
userName:''
};
}
toggle = () => {
this.setState( (prevState) => ({
isOpen: !prevState.isOpen
}));
}
getUsers = (e) => {
const {value} = e.target;
console.log('get users called='+value);
fetch('https://api.github.com/search/users?q='+ value)
...
}
}
and:
class UserList extends Component {
// Use default constructor
render() {
const users = this.props.userList.map( (user) => (
<div className="jumbotron container" key={user.login}>
{user.login}
</div>
));
return (
<div className="container-fluid">
<br />
{users}
</div>
);
}
}
parent component change should be.
getUsers(e) {
console.log('get users called='+e.target.value);
fetch('https://api.github.com/search/users?q='+ e.target.value)
.then(res => res.json())
.then(
userList =>{
this.setState({userList: userList.items})
console.log(userList);
}
);
}
Change your user list and check initially values are there or not and you dont need to user state in userList component.
that is all because initially there are no values also there can be an case when you are setting state for userList value after fetching data that might be coming as null undefined or something else so put an console log there and check that too.
class UserList extends Component {
render() {
return (
{
this.props.userList && this.props.userList.length && this.props.userList.map((user)=>
{user.login}
)
}
</div>
);
}
}
export default UserList;

onClick in reactjs not working

Below is my code. My onClick is nor working. It always through error "Uncaught TypeError: Cannot read property 'likeQuestion' of undefined". But my "gotoPage" function is working. I don't know where I am wrong. I am very new in Reactjs. Why "likeQuestion" function is not recognized.
My first onClick is working
export default class Question extends React.Component {
constructor(){
super();
this.toggle = this.toggle.bind(this);
this.state = {
pageNo : 1,
dropdownOpen: false,
questioninfo : []
}
}
componentWillMount(){
//some action
}
gotoPage(index) {
//some action. This is working
}
toggle() {
this.setState({
dropdownOpen: !this.state.dropdownOpen
});
}
likeQuestion(e){
console.log('this is clicked');
//But this is not working
}
render() {
var canvases = this.state.questionItem.map(function(data,i) {
var firstLtr = data.user_name.charAt(0);
return (
<div key={i}>
<Col sm="12" md={{ size: 12, offset: 2 }} className="questionCard">
<Card block>
<CardTitle>
<div className="outerCircle"><span>{firstLtr}</span></div> {data.user_name}
<i className="fa fa-flag-o flagging" aria-hidden="true"></i>
{data.location_url}
</CardTitle>
<CardText className="questionTxt">{data.message}</CardText>
<div>
<Button className="replyBtn" disabled>No Discussion</Button>
<Button size="sm" color="link" className="disussionSpan" onClick={(i) => this.likeQuestion(i)}>{data.likes} Likes</Button>
</div>
</Card>
</Col>
</div>
);
});
return(
<div className="container">
<div className="row">
<div className="pageInfo">
<Dropdown className="inline" isOpen={this.state.dropdownOpen} toggle={this.toggle}>
<DropdownToggle caret>
Pages
</DropdownToggle>
<DropdownMenu>
{pgrow}
</DropdownMenu>
</Dropdown>
<p className="inline currPgNo">Page: {currentPage}</p>
</div>
<div className="col-md-8 col-md-offset-2">
{canvases}
</div>
</div>
</div>
)
}
React wouldn't auto-bind map inside render(), so you have to do it yourself in order to use this and call this.likeQuestion. Luckily, map provides a second argument to specify the context (this).
So just use...
this.state.questionItem.map(function(data,i) {
...
}, this)
instead of
this.state.questionItem.map(function(data,i) {
...
})
Option 2: Use arrow function in the map, such as map((data, i) => ...
Option 3: bind this to likeQuestion in the constructor of the component.
Try to define your helper functions using arrow functions
gotoPage = (index) => {
//some action. This is working
}
toggle = () => {
this.setState({
dropdownOpen: !this.state.dropdownOpen
});
}
likeQuestion = (e) => {
console.log('this is clicked');
//But this is not working
}
or
Bind these methods in constructor of your React component. e.g
this.likeQuestion = this.likeQuestion.bind(this);
// Needs to be done for all the helper methods.
So that you access the class level this context.
E.g a minimal setup
class Question extends React.Component {
constructor(props) {
super(props);
this.state = {
likes:10
};
}
likeQuestion = (e) => {
console.log('this is clicked');
//But this is not working
}
render() {
return ( < div >
< button size = "sm"
color = "link"
className = "disussionSpan"
onClick = {
(i) => this.likeQuestion(i)
} > {
this.state.likes
}
Likes < /button>
< /div >
);
}
};
ReactDOM.render( < Question / > , document.querySelector('#test'));
<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="test">
</div>

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