I've stumbled upon a trouble with rendering list items inside the component. What am I doing wrong and how to fix it?
This is what I've got in state
this.state = {
tasksState: false,
cupsState: false,
...
citizensData: [
{
diamsEarned: 5,
rubiesEarned: 6,
}, ...
]
}
Throphies are given as props
<Citizens tasksState={this.state.tasksState}
cupsState={this.state.cupsState}
trophies={this.state.citizensData} />
const Citizens = (props) => {
let {
tasksState,
cupsState,
trophies
} = {...props};
let CitizensList = [];
for (let i=0; i<20; i++) {
CitizensList.push(
<div className="Citizens__container--block">
<div className="box label-box">
<label className="label-ct" htmlFor="citiz">Citizen {i+1}:</label>
</div>
...
<div className="box diamond-box">
<i className="fas fa-gem icon icon-diamond"></i>
<p>{trophies[i].diamsEarned}</p>
</div>
<div className="box ruby-box">
<i className="fas fa-gem icon icon-ruby"></i>
<p>{trophies[i].rubiesEarned}</p>
</div>
);
}
return (
<div className="Citizens">
<div className="Citizens__container">
<CitizensList />
</div>
</div>
);
}
As a result, list ain't rendered at all
You can replace this line:
<CitizensList />
with this:
{[...Array(20)].map(i => (
<div className="Citizens__container--block" key={i}>
<div className="box label-box">
<label className="label-ct" htmlFor="citiz">Citizen {i+1}:</label>
</div>
...
<div className="box diamond-box">
<i className="fas fa-gem icon icon-diamond"></i>
<p>{trophies[i].diamsEarned}</p>
</div>
<div className="box ruby-box">
<i className="fas fa-gem icon icon-ruby"></i>
<p>{trophies[i].rubiesEarned}</p>
</div>
</div>
))}
Though I recommend creating a component for the citizen.
In react it better to use components, more components more flexibility. If I were to do the same task I would create another functional component for your
CitizensList
yet you can follow the below approach,
Here i = number of iteration and also you are missing a closing div.
const Citizens = (props) => {
let {
tasksState,
cupsState,
trophies
} = {...props};
let i = 20;
return (
<div className="Citizens">
<div className="Citizens__container">
{
Array.from(Array(i)).map((j) =>
<div className="Citizens__container--block">
<div className="box label-box">
<label className="label-ct" htmlFor="citiz">Citizen {j+1}:</label>
</div>
...
<div className="box diamond-box">
<i className="fas fa-gem icon icon-diamond"></i>
<p>{trophies[j].diamsEarned}</p>
</div>
<div className="box ruby-box">
<i className="fas fa-gem icon icon-ruby"></i>
<p>{trophies[j].rubiesEarned}</p>
</div>
</div>
))
}
</div>
</div>
);
}
Related
i konw there are similar question to this but i couldn't find the solution.
i'm trying to loop through this "div" with data coming from django rest api (JSON format)
async componentDidMount() {
const response = await fetch('/api/Post');
const data = await response.json();
this.setState({
posts: data.data[0],
loading: false
});
}
<div class="row">
<div class="col-md-6 col-6 paddding animate-box" data-animate-effect="fadeIn">
<div class="fh5co_suceefh5co_height_2"><img src={image} alt="img"/>
<div class="fh5co_suceefh5co_height_position_absolute"></div>
<div class="fh5co_suceefh5co_height_position_absolute_font_2">
<div class=""> <i class="fa fa-clock-o"></i> {date_posted} </div>
<div class=""> {title} </div>
</div>
</div>
</div></div>
i tried to use "map" but i'm not sure how
function renderposts() {
const postList = [];
for(let i = 0; i < this.state.posts.length; i++) {
let title = `${this.state.posts[i].title}`;
let image = this.state.posts[i].image;
let date_posted = this.state.posts[i].date_posted;
let key = this.state.posts[i].id.value;
postList.push(<Post
<div class="row">
<div class="col-md-6 col-6 paddding animate-box" data-animate-effect="fadeIn">
<div class="fh5co_suceefh5co_height_2"><img src={image} alt="img"/>
<div class="fh5co_suceefh5co_height_position_absolute"></div>
<div class="fh5co_suceefh5co_height_position_absolute_font_2">
<div class=""> <i class="fa fa-clock-o"></i> {date_posted} </div>
<div class=""> {title} </div>
</div>
</div>
</div></div>
/>);
}
return postList;
}
try like this in your render method:
{this.state.posts.map((post) => {
return (
<div
class="col-md-6 col-6 paddding animate-box"
data-animate-effect="fadeIn"
>
<div class="fh5co_suceefh5co_height_2">
<img src={post.image} alt="img" />
<div class="fh5co_suceefh5co_height_position_absolute"></div>
<div class="fh5co_suceefh5co_height_position_absolute_font_2">
<div class="">
<a href="#" class="color_fff">
{" "}
<i class="fa fa-clock-o"></i> {post.date_posted}{" "}
</a>
</div>
<div class="">
<a href="single.html" class="fh5co_good_font_2">
{" "}
{post.title}{" "}
</a>
</div>
</div>
</div>
</div>
);
})}
here is a codesandbox example using hooks:
codesandbox
I assume that data.data[0] is an array of data. In React, when you want to loop through a array of data, always use method that return a clone of your data such as map or filter to avoid problem with immutability. Here's the specific code for your problem:
const postList = this.state.posts.map((post) => {
// Destructuring assignment
const { title, image, date_posted } = post;
const key = post.id.value;
return (
<div class="row">
<div
class="col-md-6 col-6 paddding animate-box"
data-animate-effect="fadeIn"
>
<div class="fh5co_suceefh5co_height_2">
<img src={image} alt="img" />
<div class="fh5co_suceefh5co_height_position_absolute"></div>
<div class="fh5co_suceefh5co_height_position_absolute_font_2">
<div class="">
<a href="#" class="color_fff">
{' '}
<i class="fa fa-clock-o"></i> {date_posted}{' '}
</a>
</div>
<div class="">
<a href="single.html" class="fh5co_good_font_2">
{' '}
{title}{' '}
</a>
</div>
</div>
</div>
</div>
</div>
);
});
I have 4 components in my project, that have the APIs, and there information.
the App.js includes the APIs:
This is in my Country.js Component
render() {
const DataGroup = this.props.countries.map((county) => {
return <InfoData info={county} />;
});
const DataGroupAll = this.props.countriesAll.map((country) => {
return <InfosData infos={country} />;
});
return (
<div>
{DataGroup}
{DataGroupAll}
</div>
);
}
and the InfoData.js
<div class="card-columns">
<div class="card-body">
<h5 class="card-title">Date : {this.props.info.updated_at}</h5>
<p class="card-text">Confirmed : {this.props.info.today.confirmed}</p>
<p class="card-text">Deaths : {this.props.info.today.deaths}</p>
</div>
</div>
and the InfosData.js
<div class="card-deck">
<div class="card">
<img src={this.props.infos.flag} width="180" height="130" />
<div class="card-body">
<h4 class="card-title">Name : {this.props.infos.name}</h4>
<p class="card-text">Capital : {this.props.infos.capital}</p>
<p class="card-text">
Currency :
{this.props.infos.currencies.map((country) => {
return country.code;
})}
</p>
<p class="card-text">
Languages :
{this.props.infos.languages.map((country) => {
return country.name + ',';
})}
</p>
<p class="card-text">Timezones : {this.props.infos.timezones}</p>
</div>
</div>
</div>
but all the information I got will be in separate cards, how can I combine them by the country code ?
How can I pass the props from the ProductFeatures to the renderFeatures function ?
Below is a sample code:
const renderFeatures = (feature) => {
return (
<div key={feature.productFeatureTypeId} className="panel panel-default">
<div className="panel-heading">
<div className="row row-no-border row-h-10">
<div className="col-xs-10">
<a
className="accordion-toggle"
data-toggle="collapse"
href={"#" + feature.productFeatureTypeId}
>
<h4 className="panel-title">{feature.productFeatureTypeId}</h4>
</a>
</div>
<div className="col-xs-2 text-right font-size-16">
<span className="glyphicon glyphicon-circle-arrow-down"></span>
</div>
</div>
</div>
<div
id={feature.productFeatureTypeId}
className="panel-collapse collapse in"
>
<div className="panel-body">
{feature.productFeaturesDescription.map(renderFeatureObjItem)}
</div>
</div>
</div>
);
};
const ProductFeatures = (props) => {
let mappedProductFeaturesMembers = getMappedProductFeaturesMembers(
props.product.productFeatureMembers
);
return (
<div className="panel-group" id="accordion">
{mappedProductFeaturesMembers.map(renderFeatures)}
</div>
);
};
Note that all this code is inside one file named ProductFeatures.js and I am using functional components.
You can just pass it in the rednerFeatures like this:
const renderFeatures = (feature, props) => { // Accept both feature and props
return (
<div key={feature.productFeatureTypeId} className="panel panel-default">
<div className="panel-heading">
<div className="row row-no-border row-h-10">
<div className="col-xs-10">
<a
className="accordion-toggle"
data-toggle="collapse"
href={"#" + feature.productFeatureTypeId}
>
<h4 className="panel-title">{feature.productFeatureTypeId}</h4>
</a>
</div>
<div className="col-xs-2 text-right font-size-16">
<span className="glyphicon glyphicon-circle-arrow-down"></span>
</div>
</div>
</div>
<div
id={feature.productFeatureTypeId}
className="panel-collapse collapse in"
>
<div className="panel-body">
{feature.productFeaturesDescription.map(renderFeatureObjItem)}
</div>
</div>
</div>
);
};
const ProductFeatures = (props) => {
let mappedProductFeaturesMembers = getMappedProductFeaturesMembers(
props.product.productFeatureMembers
);
return (
<div className="panel-group" id="accordion">
{mappedProductFeaturesMembers.map(feature => renderFeatures(feature, props))} // Pass props here too
</div>
);
};
I am using React 16 with Bootstrap 4.
I am using bootstrap modal to display some values. I need to reset these values whenever modal is closed.
For Modal I have created a separate component. I dont want to use React-Modal as I get all the functionality in the current modal.
I know in plain javascript it is achieved using below code:
$(".modal").on("hidden.bs.modal"){
//reset values here
};
But I dont know how this is achieved in ReactJS?
Below is my code for modal:
<div className="modal fade modal-flex" id="large-Modal-OneUser" tabIndex={-1} role="dialog">
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header" style={{display: 'block'}}>
<div className="row">
<div className="col-md-6">
<h2 style={{fontWeight:600}}>{newTimelineData.length > 0 ? newTimelineData[0].candidateName : ""}</h2>
</div>
<div className="col-md-6">
<span style={{display: 'inline-flex',alignItems: 'center',float:'right'}}><h4 style={{paddingRight:20}}>{isNotEmpty(this.state.scheduledFor) ? moment(this.state.scheduledFor).format("DD-MMM-YYYY"):this.checkScheduledFor(newTimelineData)}</h4>
<h3 style={{paddingRight: 10}}>{isNotEmpty(this.state.probability) ? this.getProbabilityHTML() : this.checkProbability(newTimelineData)}</h3>
{/*<button type="button" className="close" data-dismiss="modal" aria-label="Close" style={{marginTop: 0,marginBottom: 10}}>
<span aria-hidden="true">×</span>
</button>*/}
</span>
</div>
</div>
</div>
<div className="modal-body">
<div className="col-md-12">
{/*<div className="card">*/}
{/*<div className="card-block">*/}
{/* Horizontal Timeline start */}
<div className="cd-horizontal-timeline">
<div className="timeline">
<div className="events-wrapper">
<div className="events" id="foo">
<ol>
{newTimelineData.map((item, index) => (
<li key={item.id}>
<a
href="#0" onClick={()=> this.setHeaders(item)}
data-date={moment(item.scheduledFor).format('DD/MM/YYYY')}
className={index === 0 ? 'selected' : null}>
<Moment unix format="DD MMM">
{item.scheduledFor / 1000}
</Moment>
</a>
</li>
))}
</ol>
<span className="filling-line" aria-hidden="true" />
</div>
{/* .events */}
</div>
{/* .events-wrapper */}
<ul className="cd-timeline-navigation">
<li>
<a href="#0" className="prev inactive">
Prev
</a>
</li>
<li>
<a href="#0" className="next">
Next
</a>
</li>
</ul>
{/* .cd-timeline-navigation */}
</div>
{/* .timeline */}
<div className="events-content">
<ol>
{newTimelineData.map((item, index) => (
<li
key={item.id}
className={index === 0 ? 'selected' : null}
data-date={moment(item.scheduledFor).format('DD/MM/YYYY')}>
<div className="row">
<div className="col-sm-8" style={{fontSize:'1rem',paddingLeft: 3,paddingRight:0}}><b>Job</b> : {item.jobName}</div>
{isNotEmpty(joiningDate) && <div className="col-sm-4" style={{fontSize:'1rem',paddingLeft: 3,paddingRight:0}}><b>Joined Date : </b>{joiningDate}</div>}
</div>
<div className="row">
<div className="col-sm-8" style={{fontSize:'1rem',padding:0}}><b>Stage</b> : {this.props.stage}</div>
{isNotEmpty(offerDate) && <div className="col-sm-4" style={{fontSize:'1rem',paddingLeft: 0,paddingRight:0}}><b>Offer Date : </b>{offerDate}</div>}
</div>
<br></br>
<div className="row">
<div className="col-sm-12" style={{fontSize:'1rem',paddingLeft: 0}}><b>Comments</b> :<br></br>{item.comments}</div>
</div>
</li>
))}
</ol>
</div>
{/* .events-content */}
</div>
{/* Horizontal Timeline end */}
{/*</div>*/}
{/*</div>*/}
</div>
</div>
<div className="modal-footer">
<button style={{backgroundColor: '#8080808f',borderColor:'#8080808f'}}
type="button"
className="btn btn-primary waves-effect waves-light"
data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
Can anyone help?
See below snapshot for the work around I have tried suggested by #Jayavel.
Implemented a small workaround and hope it's fulfills your need, With my understanding you load your modal body with state and user will change something and you store those in the same state.
While closing the modal(close button) you need to reset the initial state i.e reset to default values.
Is that right !!! check this demo
what you need is,
store your default state like below:
const initialState = {
isOpen: false,
value: "defaultvalue"
};
and in component :
class App extends Component {
constructor(props) {
super(props);
this.state = initialState; // stored defaultstate
}
toggleModal = () => {
this.setState({
isOpen: !this.state.isOpen
});
}
toggleModalClose = () => { // modal close to reset input val
this.setState(initialState);
}
handleChange = (e) => {
this.setState({
value: e.target.value //input new value
});
}
render() {
return (
<div className="App">
<button onClick={this.toggleModal}>
Open the modal
</button>
<Modal show={this.state.isOpen}
onClose={this.toggleModalClose}>
<input type="text" value={this.state.value} onChange={this.handleChange} />
</Modal>
</div>
);
}
}
Hope this helps.
can you help me understand why this onClick event does not bind to the button and won't fire?
class DateSlider extends React.Component{
constructor(props){
super(props);
this.state = {
allValues: this.props.allValues,
}
this.onClick = this.onClick.bind(this);
}
onClick(){
console.log('here');
// this.props.change(event.target.text);
}
render(){
return (
<div class="date-slider col-xl-4 col-12">
<div class="row">
<div class="date-input-description col-xl-12 col-12">{this.props.unit}</div>
<div class="col-xl-12 date-picker-container">
<div class="col-xl-12">
<div class="row" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<div class="date-range col-xl-9 col-9">{this.props.initialValue}</div>
<div class="col-xl-3 col-9 date-picker-small-button">
<img class="mx-auto d-block" src="./images/small-arrow-down.svg" />
</div>
<div class="dropdown-menu dropdown-menu-right">
{
//HERE
this.state.allValues.map((value) => {
return <button key={value} class="dropdown-item" type="button" onClick={this.onClick}>{value}</button>
})
}
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
When clicking on the item that is rendered, it won't console.log anything.
this.state.allValues.map((value) => {
return <button key={value} class="dropdown-item" type="button" onClick={this.onClick}>{value}</button>})
should be
this.state.allValues.map((value) => {
return <button key={value} className="dropdown-item" type="button" onClick={this.onClick}>{value}</button>})
In other words: replace the class attribute with className.