Reputation: 715
I have an accordian component, I use useRef to measure the children height. But I have functionality on the children to change the content, but the children's measurement didn't update, unless I click on the toggle again.
const Accordian = ({ isOpen, children }) => {
const chilRef = useRef();
const [childHeight, setChildHeight] = useState(0);
useEffect(() => {
if (isOpen) {
const childHeight = chilRef.current && chilRef.current.scrollHeight;
setChildHeight(childHeight);
}
}, [isOpen]);
return (
<div
style={{
display: isOpen ? "block" : "none"
}}
>
<div ref={chilRef}>
{children}
<br />
<br />
<div>ChildHeight: {childHeight}</div>
</div>
</div>
);
};
export default function App() {
const [boxOpen, setBoxOpen] = useState(true);
const [expandChild, setExpandChild] = useState(false);
return (
<div className="App">
<button
onClick={() => {
setBoxOpen(prev => !prev);
}}
>
Toggle box
</button>
<Accordian isOpen={boxOpen}>
{expandChild ? (
<>
<h1>Hello CodeSandbox</h1>
<div>This has more content</div>
<div>More content......</div>
</>
) : (
<>
<div>Hello</div>
<button
onClick={() => {
setExpandChild(true);
}}
>
Expand child
</button>
</>
)}
</Accordian>
</div>
);
}
https://codesandbox.io/s/jovial-rgb-vcqnz?file=/src/App.js:83-1435
How do I get the children height every time the children changed?
Upvotes: 0
Views: 3034
Reputation: 8135
Your logic is wrong...First-time toggle did not change value of isOpen
, so useEffect never run
. Once u change to false then it re-run useEffect
.
You have to move to expend logic in the child component. Or use forwarRef
to calculate height in parent
.
Logs:
Before: useEffecttrue 0
Before: useEffecttrue 0
Inside: useEffecttrue 73
Before: useEffecttrue 73
Before: useEffecttrue 73
expend...
Before: useEffecttrue 73
Before: useEffecttrue 73
toggle::...
Before: useEffectfalse 73
Before: useEffectfalse 73
Inside: useEffectfalse 0
Before: useEffectfalse 0
Before: useEffectfalse 0
Sample Solution: https://codesandbox.io/s/awesome-allen-evmhb?file=/src/App.js:0-1515
Upvotes: 0
Reputation: 715
Just pass the children to hook's dependencies.
const Accordian = ({ children }) => {
const chilRef = useRef();
const [childHeight, setChildHeight] = useState(0);
useEffect(() => {
if (children) {
const childHeight = chilRef.current && chilRef.current.scrollHeight;
setChildHeight(childHeight);
}
}, [children]);
return (
<div>
<div ref={chilRef}>
{children}
<br />
<br />
<div>ChildHeight: {childHeight}</div>
</div>
</div>
);
};
https://codesandbox.io/s/smoosh-hooks-u8pnt
Upvotes: 1