Предположим, у вас есть простое приложение для реагирования (см. Мой codeandbox):
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>
Но я бы хотел иметь возможность использовать для этого рендер-опору! Какие-либо предложения?
2 ответа
Не совсем уверен, подходит ли это вашему случаю, но, может быть, вы можете передать функцию 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'));
Единственная проблема, которую я здесь вижу, заключается в том, что при первоначальном рендеринге this.example не будет доступен (поэтому я добавил охранник в журнал консоли), и после его установки повторный рендеринг не будет запущен (поскольку он установлен на экземпляре а не в состоянии). Если требуется повторный рендеринг, мы можем сохранить ссылку в состоянии компонента или принудительно выполнить повторный рендеринг.
С другой стороны, если вам понадобится ссылка для использования в каком-либо обработчике событий позже, это должно помочь без повторной визуализации.
Посмотрите внимательно, ключевое слово 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
является производным от текущего закрытия.
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.