Есть ли способ доступа к экземпляру родительского компонента в React?
Я знаю, что это не функциональный подход, чтобы иметь возможность сделать что-то вроде this.parent
в компоненте React, и я не могу найти никаких свойств на экземпляре компонента React, который приводит к родительскому элементу, но я просто глядя, чтобы иметь возможность делать некоторые вещи, когда мне это нужно.
Прежде, чем кто-нибудь потеряет время, объяснив это не функциональным "образом", понимаем, что мне это нужно из-за следующего, которого я пытаюсь достичь:
Постройте транспилятор для механизма Template для Meteor Spacebars, модель рендеринга которого принимает во внимание родительские компоненты/шаблоны.
Я уже создал транспилятор, который модифицирует выходной jsx для достижения этого. Я делаю это, передавая parent={this}
во всех дочерних компонентах. Однако после того, как мне пришло в голову, возможно, я просто ничего не знаю о том, что даст мне способ доступа к экземпляру родительского компонента без дополнительных модификаций транспиляции.
Любые советы будут высоко оценены.
Ответы
Ответ 1
Обновление для React 0.13 и новее
Component._owner
был устаревшим в React 0.13, а _currentElement
больше не существует в качестве ключа в this._reactInternalInstance
. Поэтому, используя нижеприведенное решение, бросаем Uncaught TypeError: Cannot read property '_owner' of undefined
.
Альтернативой является, начиная с React 16, this._reactInternalFiber._debugOwner.stateNode
.
Вы уже поняли, что это не очень хорошо делать почти всегда, но я повторяю его здесь для людей, которые не очень хорошо читают вопрос: Это, как правило, неправильный способ получить вещи, сделанные в Реагировании.
В публичном API ничего нет, что позволит вам получить то, что вы хотите. Вы можете получить это, используя внутренности React, но поскольку это частный API, который может сломаться при в любое время.
Повторяю: вы почти наверняка не будете использовать это в каком-либо производственном коде.
Тем не менее, вы можете получить внутренний экземпляр текущего компонента с помощью this. _reactInternalInstance
. Там вы можете получить доступ к элементу через свойство _currentElement
, а затем экземпляр владельца через _owner._instance
.
Вот пример:
var Parent = React.createClass({
render() {
return <Child v="test" />;
},
doAThing() {
console.log("I'm the parent, doing a thing.", this.props.testing);
}
});
var Child = React.createClass({
render() {
return <button onClick={this.onClick}>{this.props.v}</button>
},
onClick() {
var parent = this._reactInternalInstance._currentElement._owner._instance;
console.log("parent:", parent);
parent.doAThing();
}
});
ReactDOM.render(<Parent testing={true} />, container);
И здесь рабочий пример JSFiddle: http://jsfiddle.net/BinaryMuse/j8uaq85e/
Ответ 2
Нет ничего плохого, если вам нужно получить доступ к родительским реквизитам и функциям от детей.
Дело в том, что вы никогда не должны использовать внутренности React и недокументированные API.
Прежде всего, они, скорее всего, изменятся (сломают ваш код) и, самое главное, есть много других подходов, которые являются более чистыми.
Передача реквизита для детей
class Parent extends React.Component {
constructor(props) {
super(props)
this.fn = this.fn.bind(this)
}
fn() {
console.log('parent')
}
render() {
return <Child fn={this.fn} />
}
}
const Child = ({ fn }) => <button onClick={fn}>Click me!</button>
Рабочий пример
Использование контекста (если нет прямого отношения родителя/дочернего элемента)
class Parent extends React.Component {
constructor(props) {
super(props)
this.fn = this.fn.bind(this)
}
getChildContext() {
return {
fn: this.fn,
}
}
fn() {
console.log('parent')
}
render() {
return <Child fn={this.fn} />
}
}
Parent.childContextTypes = {
fn: React.PropTypes.func,
}
const Child = (props, { fn }) => <button onClick={fn}>Click me!</button>
Child.contextTypes = {
fn: React.PropTypes.func,
}
Рабочий пример