Mike Yermolayev
Mike Yermolayev

Reputation: 158

How to rerender parent component after receiving child's ref with useRef hook?

I'm banging my head trying to work around one annoying problem:

I have a parent component and a child one. The child has absolute positioning and dynamic height. I need to calculate the parent's margin depending on the child's height. I tried to do something like

const Parent = () => {
  const childRef = useRef(null);
  return (
     <Child saveRef={ref} />
);

const Child = ({saveRef}) => (<div ref={saveRef}> </div>);

But the problem is that Parent component doesn't rerender when Ref is fulfilled. How can I rerender Parent component after Ref is received?

Thanks in advance for any help and advice.

Upvotes: 2

Views: 2932

Answers (2)

Shubham Khatri
Shubham Khatri

Reputation: 282040

Write an effect in parent that run on intial mount. This effect will run after the ref is initialized and child in rendered. After this maintain a state in parent which is the margin that you need to calculate and once you calculate the margin update the state

const Parent = () => {
  const childRef = useRef(null);
  const [margin, updateMargin] = useState(0);
  useEffect(() => {
     // calculate margin. Let call it margin
     updateMargin(margin);
  }, []);

  return (
     <Child saveRef={ref} />
);

const Child = ({saveRef}) => (<div ref={saveRef}> </div>);

EDIT: In order to update on window resize, you need to add an event listener on window resize and recalculate height

const Parent = () => {
  const childRef = useRef(null);
  const [margin, updateMargin] = useState(0);
  useEffect(() => {
     window.addEventListener('resize', handleResize);
     () => {
         window.removeEventListener('resize', handleResize);
     }
  }, []);

  const handleResize = () => {
       // use ref, calcualte margin and update
  }
  return (
     <Child saveRef={ref} />
);

Upvotes: 3

Vishnu
Vishnu

Reputation: 1701

You can pass a function as prop to the child from parent, and call that function when you need to re-render the parent. Changing a state would trigger a render. So in the function you can just Change a state.

class Parent extends React.Component{
 state = {ref : null}

 handleRef = ref => {
  this.setState({ ref });
  // your add you method for changing margin
 }

 render(){
   return <Child ref={this.state.ref} handleRefChange={this.handleRef} />
 }
}

Store the ref in Parent component and call the handleRefChange from Child component to update it.

Upvotes: 0

Related Questions