Fallen Angel
Fallen Angel

Reputation: 183

How to access parent ref from child

I have some problem to pass the ref to child element in JSX. Please, see the following:

import React from "react";
import ReactDOM from "react-dom";

class App extends React.Component {
  render() {
    return (
      <div id="parent" ref={element => (this.parentRef = element)}>
        <canvas id="child" width={this.parentRef.offsetWidth} />
      </div>
    );
  }
}

ReactDOM.render(document.getElementById("app"), <App />);

I want to access #parent width from #child. How it is possible?

Upvotes: 3

Views: 23810

Answers (3)

Wide Awake
Wide Awake

Reputation: 1479

This is where React starts tying itself in knots. I've got a simple answer below (but I wasted too much time working this out)

My solution - just use javascript - specifically ".parentElement"

In the child element - you can get a reference to the child and from that you can get its parent. eg:

// Child component

    const childRef = useRef(null);
    
    <div ref={childRef}> ..... </div>

Then to get the parent element within the child just use:

childRef.current.parentElement 

Upvotes: 0

charri
charri

Reputation: 1052

This is very late, but I have a solution using the latest React hooks and functional components for future viewers. Due to the way how refs work, they do not cause a re-render on value change. However, mozilla added something called ResizeObserver: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver , which watches components for resize.

import React, { useRef, useEffect, useState } from "react";
import ResizeObserver from "resize-observer-polyfill";

export default function App() {
  const parentRef = useRef(null);
  const [width, setWidth] = useState(0);

  useEffect(() => {
    const ro = new ResizeObserver((entries) => {
      entries.forEach((entry) => setWidth(entry.contentRect.width));
    });
    ro.observe(parentRef.current);
    return () => ro.disconnect();
  }, []);

  return (
    <div ref={parentRef}>
      <div> {width} </div>
    </div>
  );
}

code in action: https://codesandbox.io/s/reverent-galileo-q7np5?file=/src/App.js

Upvotes: 2

Yaroslav Stasyuk
Yaroslav Stasyuk

Reputation: 77

In your particular example you're just getting width of an element and passing it to another element. If you're using latest react version you should checkout new ref's api (https://reactjs.org/docs/refs-and-the-dom.html) And your example will look something like that

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      width: 0
    };
    this.parentRef = React.createRef();
  }
  componentDidMount() {
    window.addEventListener("resize", this.onResize);
    this.onResize();
  }
  componentWillUnmount() {
    window.removeEventListener("resize", this.onResize);
  }
  onResize = () => {
    this.setState({
      width: this.getParentSize()
    });
  };
  getParentSize() {
    return (this.parentRef.current && this.parentRef.current.offsetWidth) || 0;
  }
  render() {
    return (
      <div id="parent" ref={this.parentRef}>
        <canvas
          id="child"
          width={this.getParentSize()}
          style={{ background: "red" }}
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

Upvotes: 0

Related Questions