I'm currently working on an accordion ponent in react version 16.3.2, that receives props from another ponent and displays the accordion accordingly. Unfortunately I cannot use hooks.
This works pretty smoothly, what I want to implement now is a way so that only one accordion can be opened at the same time on the same page. So, once you open one accordion (while another is already opened) it should automatically close the already opened one.
I have an Id (string which describes the current section, e.g 'contact', 'info', etc.) and the state of an accordion gets saved in the state (set to true when you toggle the accordion). I'm not quite sure on how I could implement this mechanism and am looking for tips on how I could solve this in a smart way. Any pointers?
example: (I didn't add all of the styling, animations since this is more about functionality)
I'm currently working on an accordion ponent in react version 16.3.2, that receives props from another ponent and displays the accordion accordingly. Unfortunately I cannot use hooks.
This works pretty smoothly, what I want to implement now is a way so that only one accordion can be opened at the same time on the same page. So, once you open one accordion (while another is already opened) it should automatically close the already opened one.
I have an Id (string which describes the current section, e.g 'contact', 'info', etc.) and the state of an accordion gets saved in the state (set to true when you toggle the accordion). I'm not quite sure on how I could implement this mechanism and am looking for tips on how I could solve this in a smart way. Any pointers?
example: https://codesandbox.io/s/reactjs-accordion-automatic-close-mechanism-6dys1 (I didn't add all of the styling, animations since this is more about functionality)
Share Improve this question edited Jan 16, 2020 at 15:12 networkcore asked Jan 16, 2020 at 13:33 networkcorenetworkcore 1451 silver badge12 bronze badges 4- use a function to close all accordions and call it on every accordion click! – Bhavya Singh Commented Jan 16, 2020 at 13:35
- @BhavyaSingh I'm not sure how I can distinguish it, how can I close only the accordion clicked on? I've tried using event listener but it doesn't seem to work with what I have here – networkcore Commented Jan 16, 2020 at 14:01
- Kindly make this one as you expected or working will update the missing part codesandbox.io/s/… – Beginner Commented Jan 16, 2020 at 14:02
- @DILEEPTHOMAS Thank you very much, I've updated the code: codesandbox.io/s/… – networkcore Commented Jan 16, 2020 at 14:21
2 Answers
Reset to default 3You could do something like this, using the state hook in the App ponent
export default function App() {
const items = [
{ id: 1, title: 'First Accordion', content: 'Hello' },
{ id: 2, title: 'Click me', content: 'Hello 2' },
{ id: 3, title: 'Third Accordion Accordion', content: 'Hello 3' },
]
const [selectedItem, setSelectedItem] = useState(1)
const handleClick = id => {
setSelectedItem(id)
}
return (
<div className="App">
{items.map(x => {
return (
<Accordion
key={x.id}
id={x.id}
title={x.title}
open={x.id === selectedItem}
onClick={handleClick}
>
<p>{x.title}</p>
</Accordion>
)
})}
</div>
);
}
Then your accordion ponent is a bit simpler
class Accordion extends React.Component {
accToggle() {
this.props.onClick(this.props.id);
}
sectionClasses() {
let classes = "accordion";
classes += this.props.open ? " sec-on" : "";
classes += "sec-underway";
return classes.trim();
}
render() {
return (
<section className={this.sectionClasses()} id={this.props.id}>
<div className="acc-title" onClick={this.accToggle.bind(this)}>
<h3 className="acc-text">{this.props.title}</h3>
<div className="acc-nav">
<span className="acc-toggle" />
</div>
</div>
<div className="acc-content">{this.props.children}</div>
</section>
);
}
}
Accordion.defaultProps = {
open: false
};
Accordion.propTypes = {
id: PropTypes.number.isRequired,
children: PropTypes.any,
onFocus: PropTypes.func,
progress: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string,
PropTypes.bool
]),
title: PropTypes.string,
open: PropTypes.bool
};
export default Accordion;
The accordion calls a function on the app ponent, which updates the state and the display logic is passed down in the props
You can find solution for your problem in the following codesandbox https://codesandbox.io/s/reactjs-accordion-automatic-close-mechanism-yejc0
Change prop names as it fits your code base, but the logic is solid