Reputation: 109
I'm trying do a conditional render in react, but isn't work.
That is my function:
populateBodyInstallationsEdition() {
letshow = null;
console.log(this.state.installations);
for (let i = 0; i < this.state.IdInstallGroup.length; i++) {
for (let j = 0; j < this.state.installations.length; j++) {
console.log(this.state.IdInstallGroup[i]);
console.log(this.state.installations[j].id);
if (this.state.IdInstallGroup[i] === this.state.installations[j].id) {
show = (
<div>
<div>
<input
type="checkbox"
value="None"
className="test"
id={this.state.installations[j].id}
name={this.state.installations[j].Name}
checked
/>
{/* <label htmlFor={arr[index].id} /> */}
</div>
<label htmlFor={this.state.installations[j].id}>
{this.state.installations[j].Name}
</label>
</div>
);
} else {
show = (
<div>
<div>
<input
type="checkbox"
value="None"
className="test"
id={this.state.installations[j].id}
name={this.state.installations[j].Name}
/>
{/* <label htmlFor={arr[index].id} /> */}
</div>
<label htmlFor={this.state.installations[j].id}>
{this.state.installations[j].Name}
</label>
</div>
);
}
}
}
return show;
}
the conditions are making the right comparisons but don't rende the JSX
what could be wrong ?
how can i solve this problem ?
Upvotes: 0
Views: 88
Reputation: 3413
Ok, right to the answer...
If you want to render ALL installations:
let show = null;
with let show = [];
show = (
with show.push(
That's it... Why? Because your function is iterating both arrays and always setting 'show' to the current component depending on the condition, this will always render only one component.
Updating the code as suggested above will add each one of the "conditional" components to an array that will be then rendered, not only one.
However, I can't say that it is the right solution just because it will work, let me show you other alternatives to implement this in a better way.
Option 1: Following the same approach, but without duplicating code.
Both components of the condition are exactly the same, except for the "checked" attribute, react allows you to do this:
populateBodyInstallationsEdition = () => {
let show = [];
for (let i = 0; i < this.state.IdInstallGroup.length; i++) {
for (let j = 0; j < this.state.installations.length; j++) {
show.push(
<div>
<div>
<input
type="checkbox"
value="None"
className="test"
id={this.state.installations[j].id}
name={this.state.installations[j].Name}
checked={this.state.IdInstallGroup[i] === this.state.installations[j].id} // <=PAY ATTENTION HERE
/>
</div>
<label htmlFor={this.state.installations[j].id}>
{this.state.installations[j].Name}
</label>
</div>
);
}
}
return show;
};
Relevant code checked={this.state.IdInstallGroup[i] === this.state.installations[j].id}
Option 2: Extract a component
//This component can go on a separate file
const MyComponent = ({id, name, isChecked = false}) => {
return(
<div>
<div>
<input
type="checkbox"
value="None"
className="test"
id={id}
name={name}
checked={isChecked}
/>
</div>
<label htmlFor={id}>
{name}
</label>
</div>
)
}
populateBodyInstallationsEdition = () => {
let show = [];
for (let i = 0; i < this.state.IdInstallGroup.length; i++) {
for (let j = 0; j < this.state.installations.length; j++) {
let id = this.state.installations[j].id;
let name = this.state.installations[j].Name;
let isChecked = this.state.IdInstallGroup[i] === this.state.installations[j].id;
show.push(
<MyComponent id={id} name={name} isChecked={isChecked} />
);
}
}
return show;
};
Option 3: Get rid of the 'populateBodyInstallationsEdition' function and use 'map' in the render body (Using the same component we defined before)
const installations = [
{
id: "group1",
Name: "Some name"
},
{id:..., Name:...}
...
]
class App extends React.Component {
state = {
IdInstallGroup: ["group1", "group2", "group3", "group4"],
installations: installations
};
render() {
return <div className="App">
{
this.state.IdInstallGroup.map(group =>
this.state.installations.map(installation =>
<MyComponent id={installation.id} name={installation.Name} isChecked={group === installation.id} />
)
)
}
</div>;
}
}
Upvotes: 1
Reputation: 930
import React from 'react';
const populateBodyInstallationsEdition = () => {
return (
<React.Fragment>
{
IdInstallGroup && IdInstallGroup.map((group) => {
return (
installations && installations.map((install) => {
return (
<div>
{
this.state.IdInstallGroup[group] === this.state.installations[install].id ?
<div>
<div>
<input
type="checkbox"
value="None"
className="test"
id={this.state.installations[install].id}
name={this.state.installations[install].Name}
checked
/>
{/* <label htmlFor={arr[index].id} /> */}
</div>
<label htmlFor={this.state.installations[install].id}>
{this.state.installations[install].Name}
</label>
</div>
:
<div>
<div>
<input
type="checkbox"
value="None"
className="test"
id={this.state.installations[install].id}
name={this.state.installations[install].Name}
/>
{/* <label htmlFor={arr[index].id} /> */}
</div>
<label htmlFor={this.state.installations[install].id}>
{this.state.installations[install].Name}
</label>
</div>
}
</div>
)
})
)
})
}
</React.Fragment>
)
}
export default populateBodyInstallationsEdition;
Try this way of conditional rendering. Also, You may use map to loop through the each element and put conditions inside it.
Upvotes: 0