In the image as you can see, I have a Foo page, where I have 10 Accordions, In one of the Accordions there is a Form component, When I submit the Form it calls a remote API and returns some JSON data, I convert it to a Table of content and want to show it under the Form.
The problem is I can show the Table after toggling the Accordion again after the submit button clicked, as I have set the maxheight in the onClick.
const [activeState, setActiveState] = useState("");
const [activeHeight, setActiveHeight] = useState("0px");
const toogleActive = () => {
setActiveState(activeState === "" ? "active" : "");
setActiveHeight(activeState === "active" ? "0px" :`${contentRef.current.scrollHeight}px`)
}
return (
<div className={styles.accordion_section}>
<button className={styles.accordion} onClick={toogleActive}>
<p className={styles.accordion_title}>{title}</p>
</button>
<div ref={contentRef}
style={{ maxHeight: `${activeHeight}` }}
className={styles.accordion_content}>
<div>
{content}
</div>
</div>
</div>
)
I have used context also to share the useState hook between Accordion and Form components to update the height.
<UpdateHeightContext.Provider value={{updateHeight, setUpdateHeight}}>
<Accordion title="Find your Data" content={< FormWithTwoInput firstLabel="FirstName" secondLabel="LastName" buttonColor="blue" buttonText="Check Deatils"/>} />
</UpdateHeightContext.Provider>
Is there any way to update the Accordions height dynamically when I receive the response from the API? Other than toggling it again. A similar question was asked here React accordion, set dynamic height when DOM's children change unfortunately no one replied.
Although the work around what I have found is not solid, it works completely fine for me. If anyone runs into this same problem, they might find it useful.
import React, { useState, useRef } from 'react' const Accordion = ({ title, content }) => { const [activeState, setActiveState] = useState(""); const [activeHeight, setActiveHeight] = useState("0px"); const contentRef = useRef("form") const toogleActive = () => { setActiveState(activeState === "" ? "active" : ""); setActiveHeight(activeState === "active" ? "0px" :`${contentRef.current.scrollHeight + 100}px`) } return ( <div className={styles.accordion_section}> <button className={styles.accordion} onClick={toogleActive}> <p className={styles.accordion_title}>{title}</p> </button> <div ref={contentRef} style={{ maxHeight: `${activeHeight}` }} className={styles.accordion_content}> <div> {content} </div> </div> </div> ) } Accordion.propTypes = { title: PropTypes.string, content: PropTypes.object, } export default AccordionI've coded a bit of extra space so that while the dynamic response is accepted, the contents of the table are displayed. In the CSS module file, I kept the overflow as automatic, before it was hidden.
.accordion_content { background-color: white; overflow: auto; max-height: max-content; }As a result, the table appears dynamically and the user can scroll within the accordion if my table needs more space.