I have a <div>
tag that encloses a varied number of buttons. When each button is clicked, I have a react variable that shows. My problem is that every hidden text shows whenever I click any button; however I only want the buttons to display their hidden text if I click them, so that they behave uniquely.
I have tried some ideas with conditional rendering, but I'm not sure how to attack that correctly.
I have a function that creates the buttons for each church. Here is that function:
createButtonsForChurches(arr) {
var listOfButtons = [];
for (var i = 1; i < arr.length; i++) { // loop through each church
var currentButton = (
<div>
<button onClick={this.toggle} className="churchButton">{arr[i].name}</button>
{
this.state.on && (
<div className="allContent">
<div className="individualContent">
{(arr[i].femaleStudents[0]) && this.createContentParagraphTextForArray(arr[i].femaleStudents, "Female Students")}
</div>
<div className="individualContent">
{(arr[i].femaleLeaders[0]) && this.createContentParagraphTextForArray(arr[i].femaleLeaders, "Female Leaders")}
</div>
<div className="individualContent">
{(arr[i].maleStudents[0]) && this.createContentParagraphTextForArray(arr[i].maleStudents, "Male Students")}
</div>
<div className="individualContent">
{(arr[i].maleLeaders[0]) && this.createContentParagraphTextForArray(arr[i].maleLeaders, "Male Leaders")}
</div>
</div>
)
}
</div>
);
listOfButtons.push(currentButton);
}
return listOfButtons;
}
You can see the toggle function that is called for the onClick attribute as well. Here is my toggle method and my constructor:
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
on: false
}
}
toggle() {
this.setState({
on: !this.state.on
});
}
I don't want to put too much code and complicate things - arr is an array of objects. Those objects contain 4 different arrays, and each of those arrays hold a different number of objects. So - arr is the list of churches, which contains the churches as objects, and each church contains 4 arrays (female and male students and leaders), and inside each of those 4 arrays there are members as objects wherever they belong
I do not know how to only show the hidden text for the buttons that I click. Would love some help.
You have to create an array for buttons and give property isHidden
to show/hide data on toggle. This is the working solution of your question.
class App extends React.Component {
state = {
buttons: []
};
arr = [
{
name: "churchName1",
femaleStudents: ["student1", "student1"],
femaleLeaders: ["leaders1", "leaders1"],
maleStudents: ["student1", "student1"],
maleLeaders: ["leaders1", "leaders1"]
},
{
name: "churchName2",
femaleStudents: ["student2", "student2"],
femaleLeaders: ["leaders2", "leaders2"],
maleStudents: ["student2", "student2"],
maleLeaders: ["leaders2", "leaders2"]
},
{
name: "churchName3",
femaleStudents: ["student3", "student3"],
femaleLeaders: ["leaders3", "leaders3"],
maleStudents: ["student3", "student3"],
maleLeaders: ["leaders3", "leaders3"]
}
];
componentDidMount() {
// create buttons array
let buttons = [];
for (let item of this.arr) {
let buttonObj = { id: item.name, isHidden: true };
buttons.push(buttonObj);
}
this.setState({ buttons });
}
createContentParagraphTextForArray = (para1, para2) => {
return (
<div>
{para1} {para2}
</div>
);
};
createButtonsForChurches = arr =>
arr.map((item, index) => {
let isHidden =
this.state.buttons.length > 0
? this.state.buttons[index].isHidden
: true;
return (
<div key={item.name}>
<button
onClick={() => this.clickHandler(item.name)}
className="churchButton"
>
{item.name}
</button>
{!isHidden && (
<div className="allContent">
<div className="individualContent">
{item.femaleStudents[0] &&
this.createContentParagraphTextForArray(
item.femaleStudents,
"Female Students"
)}
</div>
<div className="individualContent">
{item.femaleLeaders[0] &&
this.createContentParagraphTextForArray(
item.femaleLeaders,
"Female Leaders"
)}
</div>
<div className="individualContent">
{item.maleStudents[0] &&
this.createContentParagraphTextForArray(
item.maleStudents,
"Male Students"
)}
</div>
<div className="individualContent">
{item.maleLeaders[0] &&
this.createContentParagraphTextForArray(
item.maleLeaders,
"Male Leaders"
)}
</div>
</div>
)}
</div>
);
});
clickHandler = buttonId => {
let buttons = this.state.buttons;
buttons.forEach(button => {
if (button.id === buttonId) {
button.isHidden = !button.isHidden;
}
});
this.setState({ buttons });
};
render() {
return (
<React.Fragment>{this.createButtonsForChurches(this.arr)}</React.Fragment>
);
}
}
ReactDOM.render(<App/>, 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'/>