如何使用 React 的上下文功能将 HTML5 Canvas 上下文传递给 this.props.children?

How do I use React's Context feature to pass an HTML5 Canvas context to this.props.children?

我正试图更加熟练地了解 React 如何传递信息,于是出现了这个测试用例:

我有一个组件,由 Canvas object 和不定数量的 children 组成。我想授予 children 访问此组件的 canvas 上下文的权限。

我想知道我是否可以给组件一个带有 canvas 上下文的 React 上下文,并用它包装 children,然后让个人 children 选择成为消费者。但是,我对 React 或其生命周期还不够熟悉,无法知道如何正确地执行此操作。我完全离开了吗?这可能吗?

这是有问题的组件:

const CanvasContext = React.createContext('default');
class Screen extends React.Component
{    

  render(){

    return (<div>
              <canvas id="myCanvas" ref={(c) => this.context = c.getContext('2d')} width="200" height="100" style={{border: '1px solid black'}}></canvas> 
              <CanvasContext.Provider value = {this.context}>{this.props.children}
              </CanvasContext.Provider>
          </div>);

  }
}

现在,它包含一个 child:

class Test extends React.Component{

  render(){
    return <CanvasContext.Consumer>{ctx => {
              ctx.moveTo(0, 0);
              ctx.lineTo(200, 100);
              ctx.stroke();}}
          </CanvasContext.Consumer>;   
  }
}
ReactDOM.render(<Screen><Test/></Screen>, document.getElementsByClassName('container-fluid')[0]);

将不胜感激。

编辑:这是一个代码笔:https://codepen.io/ejpg/pen/XqvGdp

这是个好主意,但您有几个问题:

1) 你的codepen中的React版本是15.4。您正在使用的新上下文 api 是在 16.3 中引入的。这就是您的代码笔抛出错误的原因:

Uncaught TypeError: React.createContext is not a function

2) 当第一次渲染发生时,ref 还不存在,这将导致此函数调用崩溃,因为上下文可能还不存在:

ctx.moveTo(0, 0); // ctx isn't defined yet

ctx.moveTo is not a function

3) 这是使用 16.3createRef 功能的好机会,它有助于管理您的 ref;

class Screen extends React.Component {
  canvas = React.createRef();
  render() {
    return <canvas ref={this.canvas} />
  }
}

4) 获取上下文无论如何都需要在第一次渲染之后发生,然后你想在你有上下文传递它时触发重新渲染,所以状态是一个很好的地方:

class Screen extends React.Component {
  state = { context: null };
  canvas = React.createRef();
  componentDidMount() {
    this.setState({ context: this.canvas.current.getContext("2d") });
  }
  render() {
    return (
      <div>
        <canvas ref={this.canvas} />
        {this.state.context && (
          <CanvasContext.Provider value={this.state.context}>
            {this.props.children}
          </CanvasContext.Provider>
        )}
      </div>
    );
  }
}

这足以让您的测试组件在渲染时绘制!

Full code on codesandbox