Можно ли извлечь экземпляр компонента из React Fiber?
До версии 16 React - то есть до введения волокон React - можно было взять элемент DOM и извлечь экземпляр компонента React следующим образом:
const getReactComponent = dom => {
let found = false;
const keys = Object.keys(dom);
keys.forEach(key => {
if (key.startsWith('__reactInternalInstance$')) {
const compInternals = dom[key]._currentElement;
const compWrapper = compInternals._owner;
const comp = compWrapper._instance;
found = comp;
}
});
return found || null;
};
Это больше не работает для React v16, который использует новую реализацию Fiber. В частности, приведенный выше код выдает ошибку в строке const comparWrapper = compInternals._owner
потому что нет _owner
собственность больше. Таким образом, вы не можете также получить доступ к _instance
,
Мой вопрос здесь заключается в том, как бы мы извлекли экземпляр из элемента DOM в реализации Fiber v16?
2 ответа
Вы можете попробовать функцию ниже (обновлена для работы с React <16 и 16+):
window.FindReact = function(dom) {
let key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$"));
let internalInstance = dom[key];
if (internalInstance == null) return null;
if (internalInstance.return) { // react 16+
return internalInstance._debugOwner
? internalInstance._debugOwner.stateNode
: internalInstance.return.stateNode;
} else { // react <16
return internalInstance._currentElement._owner._instance;
}
}
Применение:
var someElement = document.getElementById("someElement");
FindReact(someElement).setState({test1: test2});
React 17 немного отличается:
function findReact(dom) {
let key = Object.keys(dom).find(key => key.startsWith("__reactFiber$"));
let internalInstance = dom[key];
if (internalInstance == null) return "internalInstance is null: " + key;
if (internalInstance.return) { // react 16+
return internalInstance._debugOwner
? internalInstance._debugOwner.stateNode
: internalInstance.return.stateNode;
} else { // react <16
return internalInstance._currentElement._owner._instance;
}
}
domElement в этом — это tr с именем параметра данных поля, которое вы пытаетесь изменить:
var domElement = ?.querySelectorAll('tr[data-param-name="<my field name>"]')