tscizzle tscizzle - 1 month ago 6
React JSX Question

React - Get the ref present in child component in the parent component

I'm not trying to do anything hacky using refs. I just need the ref to the element because the element is a canvas, and to draw on a canvas you need its ref.

class Parent extends Component {
clickDraw = () => {
// when button clicked, get the canvas context and draw on it.
// how?
}

render() {
return (
<div>
<button onClick={this.clickDraw}> Draw </button>
<Child />
</div>
);
}
}


class Child extends Component {
componentDidMount() {
const ctx = this.canvas.getContext('2d');
// draw something on the canvas once it's mounted
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,150,75);
}

render() {
return (
<canvas width={300}
height={500}
ref={canvasRef => this.canvas = canvasRef}>
</canvas>
);
}
}


=====

Something I tried (which technically works but feels strange) is define the
<canvas>
in the parent, so in its ref function,
this
refers to the parent component. Then I pass the
<canvas>
and
this.canvas
to the child as two separate props. I return the
<canvas>
(named
this.props.canvasJSX
) in the child's render function, and I use
this.canvas
(named
this.props.canvasRef
) to get its context to draw on it. See below:

class Parent extends Component {
clickDraw = () => {
// now I have access to the canvas context and can draw
const ctx = this.canvas.getContext('2d');
ctx.fillStyle = "#00FF00";
ctx.fillRect(0,0,275,250);
}

render() {
const canvas = (
<canvas width={300}
height={500}
ref={canvasRef => this.canvas = canvasRef}>
</canvas>
);
return (
<div>
<button onClick={this.clickDraw}> Draw </button>
<Child canvasJSX={canvas}
canvasRef={this.canvas} />
</div>
);
}
}


class Child extends Component {
componentDidMount() {
const ctx = this.props.canvasRef.getContext('2d');
// draw something on the canvas once it's mounted
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,150,75);
}

render() {
return this.props.canvas;
}
}


Is there a more standard way of achieving this?

Answer Source

You should actually be using the first approach and you can access the child elements refs in the parent

class Parent extends Component {
  clickDraw = () => {
    // when button clicked, get the canvas context and draw on it.
    const ctx = this.childCanvas.canvas.getContext('2d');
    ctx.fillStyle = "#00FF00";
    ctx.fillRect(0,0,275,250);
  }

  render() {
    return (
      <div>
        <button onClick={this.clickDraw}> Draw </button>
        <Child ref={(ip) => this.childCanvas = ip}/>;
      </div>
    );
  }
}


class Child extends Component {
  constructor() {
     super();
     this.canvas = null;
  }
  componentDidMount() {
    const ctx = this.canvas.getContext('2d');
    // draw something on the canvas once it's mounted
    ctx.fillStyle = "#FF0000";
    ctx.fillRect(0,0,150,75);
  }

  render() {
    return (
      <canvas width={300}
              height={500}
              ref={canvasRef => this.canvas = canvasRef}>
      </canvas>
    );
  }
}

You can only use this approach is the child component is declared as a class.