Я не пытаюсь сделать что-нибудь хакерское, используя ссылки. Мне просто нужна ссылка на элемент, потому что элемент является холстом, а для рисования на холсте вам нужен его реф.

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>
    );
  }
}

=====

Я попытался (что технически работает, но кажется странным) определить <canvas> в родительском элементе, поэтому в его функции ref this ссылается на родительский компонент. Затем я передаю <canvas> и this.canvas ребенку в виде двух отдельных предметов. Я возвращаю <canvas> (с именем this.props.canvasJSX) в функции рендеринга дочернего элемента и использую this.canvas (с именем this.props.canvasRef), чтобы получить контекст для рисования на нем. Увидеть ниже:

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;
  }
}

Есть ли более стандартный способ достижения этого?

10
tscizzle 25 Апр 2017 в 07:11

2 ответа

Лучший ответ

На самом деле вы должны использовать первый подход, и вы можете получить доступ к дочерним элементам ссылки в родительском

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>
    );
  }
}

Вы можете использовать только этот подход, если дочерний компонент объявлен как class.

7
Shubham Khatri 26 Апр 2017 в 05:11

Если этого нельзя избежать, предложенный шаблон извлекается из React docs будет:

import React, {Component} from 'react';

const Child = ({setRef}) => <input type="text" ref={setRef} />;

class Parent extends Component {
    constructor(props) {
        super(props);
        this.setRef = this.setRef.bind(this);
    }
    componentDidMount() {
        // Call function on Child dom element
        this.childInput.focus();
    }
    setRef(input) {
        this.childInput = input;
    }
    render() {
        return <Child setRef={this.setRef} />
    }
}

Родитель передает функцию в качестве реквизита, привязанного к this Родителю . React вызовет функцию обратного вызова Child ref setRef и присоединит свойство childInput к this, которое, как мы уже отмечали, указывает на родитель .

2
arpl 15 Окт 2017 в 17:00
43601440