无法将ref指定给渲染道具中的组件

and*_*whl 4 javascript reactjs

假设您有一个简单的反应应用程序(请参阅我的代码框):

import React from 'react';
import { render } from 'react-dom';

class RenderPropComponent extends React.Component {
  render() {
    console.log(this.example.test());
    return this.props.render();
  }
}

class Example extends React.Component {
  test = () => console.log('Test successful!');

  render() {
    return <h1>I am an example!</h1>;
  }
}

const App = () => (
  <RenderPropComponent
    render={() => {
      return (
        <Example ref={node => this.example = node} />
      )
    }}
  />
);

render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

这会导致错误:

TypeError
Cannot read property 'test' of undefined
Run Code Online (Sandbox Code Playgroud)

如何ref为通过渲染道具渲染的组件指定?

我知道我可以通过以下方式完成此任务this.props.children:

class RenderPropComponent extends React.Component {
  const childComponents = React.Children.map(this.props.children, child => {
      return React.cloneElement(child, {ref: node => this.example = node})
  });
  console.log(this.example.test());
  render() {  
    return <div>{childComponents}</div>;
  }
}

...

<RenderPropComponent>
    <Example />
</RenderPropComponent>
Run Code Online (Sandbox Code Playgroud)

但我希望能够使用渲染道具来做到这一点!有什么建议?

Gle*_*ost 7

不完全确定它是否适合您的情况,但也许您可以将setRef函数作为参数传递给渲染道具?就像在这个分叉的沙盒中一样.

import React from 'react';
import { render } from 'react-dom';
const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center',
};

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.setRef = this.setRef.bind(this);
  }
  setRef(node) {
    this.example = node; 
  }
  render() {
    console.log(this.example && this.example.test());
    return this.props.render(this.setRef);
  }
}

class Example extends React.Component {
  test = () => console.log('Test successful!');

  render() {
    return <h1>I am an example!</h1>;
  }
}

const App = () => (
  <div style={styles}>
    <Hello 
      name="CodeSandbox" 
      render={(setRef) => {
        return (
          <Example ref={setRef} />
        )
      }}
    />
    <h2>Start editing to see some magic happen {'\u2728'}</h2>
  </div>
);

render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

我在这里看到的唯一问题是,在初始渲染时,this.example将不可用(这就是为什么我在控制台日志中添加了一个防护)并且在设置之后,将不会触发重新渲染(因为它已设置)在实例而不是在状态).如果需要重新渲染,我们可以将ref存储在组件状态中或强制重新渲染.

另一方面,如果您稍后需要在某个事件处理程序中使用ref,那么应该在不重新渲染的情况下执行该操作.