假设您有一个简单的反应应用程序(请参阅我的codesandbox):
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'));
这会导致错误:
TypeError
Cannot read property 'test' of undefined
如何将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>
但我希望能够使用渲染道具来做到这一点!有什么建议吗?
答案 0 :(得分:7)
不完全确定它是否适合您的情况,但也许您可以将setRef函数作为参数传递给渲染道具?就像在这个分叉的sandbox中一样。
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'));
我在这里看到的唯一问题是,在初始渲染时,this.example将不可用(这就是为什么我在控制台日志中添加了一个防护)并且在设置之后,将不会触发重新渲染(因为它是在实例上而不是在状态中设置的)。如果需要重新渲染,我们可以将ref存储在组件状态或强制重新渲染。
另一方面,如果稍后需要在某个事件处理程序中使用ref,那么应该不用重新渲染就可以了。
答案 1 :(得分:-1)
仔细查看,this
关键字用于全局范围,而不是example
组件的范围。
const App = () => (
<RenderPropComponent
render={() => {
return (
<Example ref={node => this.example = node} />
)
}}
/>
);
如果您还没有发现它,请查看该代码段:
class Foo {
constructor(stuffToDo) {
this.bar = ‘bar’;
this.stuffToDo = stuffToDo
}
doStuff() {
this.stuffToDo();
}
}
new Foo(() => console.log(this.bar)).doStuff();
这将记录undefined
,而非bar
,因为this
来自当前的闭包。