【问题标题】:How do I use React's Context feature to pass an HTML5 Canvas context to this.props.children?如何使用 React 的 Context 功能将 HTML5 Canvas 上下文传递给 this.props.children?
【发布时间】:2018-11-06 08:47:00
【问题描述】:

我正在尝试更流畅地了解 React 如何传递信息,结果出现了这个测试用例:

我有一个由 Canvas 对象和不定数量的子对象组成的组件。我想让孩子们访问这个组件的画布上下文。

我想知道是否可以给组件一个带有画布上下文的 React Context 并用它包装子级,然后让各个子级选择成为消费者。但是,我不习惯 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>);

  }
}

现在,它包含一个孩子:

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

我们将不胜感激。

编辑:这是一个 Codepen:https://codepen.io/ejpg/pen/XqvGdp

【问题讨论】:

    标签: javascript reactjs html5-canvas react-context


    【解决方案1】:

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

    1) 你的 Codepen 中的 React 版本是15.4。您正在使用的新上下文 API 在 16.3 中介绍。这就是您的 codepen 抛出错误的原因:

    未捕获的类型错误:React.createContext 不是函数

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

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

    ctx.moveTo 不是函数

    3) 这是使用16.3createRef 函数来帮助管理您的参考的绝佳机会;

    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

    【讨论】:

    • 非常感谢您的详细帮助。我会开始做这件事。干杯!
    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 2019-01-07
    • 2018-10-24
    • 2017-11-22
    • 1970-01-01
    • 2018-03-05
    相关资源
    最近更新 更多