I have an array of objects that is like this:
data = [{
"projectId": 1,
"projectName": "Progetto 1",
"clientId": 1,
"projectDescription": "description1",
"projectMailingList": "mailingList1",
"projectCreationDate": "apr 29, 2019",
"projectVersion": 1
},
{
"projectId": 2,
"projectName": "Progetto 2",
"clientId": 1,
"projectDescription": "description2",
"projectMailingList": "mailingList2",
"projectCreationDate": "apr 29, 2019",
"projectVersion": 1
},
{
"projectId": 3,
"projectName": "Progetto 3",
"clientId": 1,
"projectDescription": "description3",
"projectMailingList": "mailingList3",
"projectCreationDate": "apr 29, 2019",
"projectVersion": 1
}];
I use the map function for this array, but it's mapping more elements than the ones present. What I have to do is to render a custom component for each of the element of the array, so that would be 3 times, instead it's creating it 7 times. I've tried doing this inside constructor, to check:
this.data.map(projectId => console.log("Call "));
and it correctly prints "Call" for 3 times. Then, in my render method I do this:
return (
<Slider class="mySlider" ref = {c => (this.slider = c)} {...this.settings}>
{
this.data.map(projectId =>
<ProjectComponent key={projectId} project={projectId} time={this.state.timestamp} originalIndex={ i++ } currentIndex = {this.state.activeSlide}></ProjectComponent>)
}
</Slider>
);
and it creates 7 ProjectComponent
s. Why is that? And why 7?
EDIT
This is ProjectComponent
:
export class ProjectComponent extends React.Component {
constructor(props) {
super(props);
this.logger = new LoggerService();
this.state = {
project: this.props.project //projects contains the needed data
};
}
componentDidMount() {
// this.logger.info("------ componentDidMount");
if(this.props.originalIndex === this.props.currentIndex) {
this.getProjectData();
}
}
componentDidUpdate(prevProps, prevState) {
if(prevProps.time !== this.props.time
&& this.props.originalIndex === this.props.currentIndex) {
this.getProjectData();
}
}
render() {
var homeService = new HomeService();
if (this.state.isLoading) {
return (
<div className="projectContainer">
<div className="container-fluid">
<div className="row">
<div className="col">
<div className='sweet-loading'>
<ClipLoader
sizeUnit={"px"}
size={100}
color={'#FFECA5'}
loading={this.state.isLoading} />
</div>
</div>
</div>
</div>
</div>
);
} else {
return (
<div className="projectContainer">
<div className="container-fluid">
<div className="row">
<div className="col">
<ProjectHeaderComponent header={this.state.project}></ProjectHeaderComponent>
{<ServiceStatusListComponent functionalities={ homeService.getProjectStatusById(this.props.id)} time={this.props.time}
originalIndex = {this.props.originalIndex} currentIndex = {this.props.currentIndex}></ServiceStatusListComponent>}
</div>
</div>
</div>
</div>
);
}
}
getProjectData() {
this.setState({
project: {},
isLoading: false
});
var homeService = new HomeService();
this.setState({
isLoading:false,
projectResponse: homeService.getProjectStatusById(this.props.id)
});
}
}
Moving
this.data.map(projectId => console.log("Call "));
to render
helps when this.data
can change in lifecycles. If hardcoded - no difference. If not render
is a better place to check state/props right before returning view.
It's better to console.log
something more meaningfull, too.
In this case it would help debugging because you're iterating over objects, not reaching real projectId
property. The same error occurs within render
. Instead of idetifier you're using refs to object - key
ing fails allowing for <ProjectComponent/>
duplicates.
There should be
this.data.map( project =>
<ProjectComponent key={project.projectId} project={project}
The <ProjectComponent />
source was not needed - component can't duplicate itself. That's why its parents needs inspection, f.e. <Slider />
(direct parent) and the 'main' component. If <Slider />
was rendered once then only the second can be a source of error.
As we have <ProjectComponent />
source, we see errors there:
this.props.id
while no id
prop passed;homeService
when condition can lead to render 'loading'