React-디버깅을 위해 DOM 요소에서 컴포넌트 가져 오기
콘솔에서 디버깅 할 목적으로 React에서 지원되는 React 컴포넌트를 얻기 위해 DOM 요소 인스턴스를 사용할 수있는 메커니즘이 있습니까?
이 질문은 프로덕션 코드에서 사용하는 맥락에서 이전에 요청되었습니다. 그러나 내 초점은 디버깅 목적으로 개발 빌드에 있습니다.
React 용 Chrome 디버깅 확장 프로그램에 익숙 하지만 모든 브라우저에서 사용할 수있는 것은 아닙니다. DOM 탐색기와 콘솔을 결합하면 '$ 0'바로 가기를 사용하여 강조 표시된 DOM 요소에 대한 정보에 쉽게 액세스 할 수 있습니다.
디버깅 콘솔에서 다음과 같은 코드를 작성하고 싶습니다. getComponentFromElement ($ 0) .props
React 개발 빌드에서도 요소의 ReactId를 사용하여 구성 요소를 가져 오는 메커니즘이 없습니까?
방금 문서를 읽었으며 외부에 노출 된 API 중 어느 것도 ID로 직접 들어가서 React 구성 요소를 찾을 수 없습니다. 그러나 초기 React.render()
호출을 업데이트 하고 반환 값을 어딘가에 유지할 수 있습니다 . 예 :
window.searchRoot = React.render(React.createElement......
그런 다음 searchRoot를 참조하고 직접 살펴 보거나 React.addons.TestUtils
. 예를 들어 이것은 모든 구성 요소를 제공합니다.
var componentsArray = React.addons.TestUtils.findAllInRenderedTree(window.searchRoot, function() { return true; });
이 트리를 필터링하기위한 몇 가지 기본 제공 메서드가 있거나 작성한 일부 검사를 기반으로 구성 요소 만 반환하도록 자체 함수를 작성할 수 있습니다.
TestUtils에 대한 자세한 내용 : https://facebook.github.io/react/docs/test-utils.html
내가 사용하는 것은 다음과 같습니다. (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 16+를 지원합니다
window.findReactComponent = function(el) {
for (const key in el) {
if (key.startsWith('__reactInternalInstance$')) {
const fiberNode = el[key];
return fiberNode && fiberNode.return && fiberNode.return.stateNode;
}
}
return null;
};
나는 DOM 노드에서 모든 반응 구성 요소에 액세스 할 수 있도록이 작은 해킹을 작성했습니다.
var ReactDOM = require('react-dom');
(function () {
var _render = ReactDOM.render;
ReactDOM.render = function () {
return arguments[1].react = _render.apply(this, arguments);
};
})();
그런 다음 다음을 사용하여 모든 구성 요소에 직접 액세스 할 수 있습니다.
document.getElementById("lol").react
또는 JQuery 사용
$("#lol").get(0).react
다음은 현재 사용중인 작은 스 니펫입니다.
React 0.14.7에서 작동합니다.
let searchRoot = ReactDom.render(ROOT, document.getElementById('main'));
var getComponent = (comp) => comp._renderedComponent ? getComponent(comp._renderedComponent) : comp;
var getComponentById = (id)=> {
var comp = searchRoot._reactInternalInstance;
var path = id.substr(1).split('.').map(a=> '.' + a);
if (comp._rootNodeID !== path.shift()) throw 'Unknown root';
while (path.length > 0) {
comp = getComponent(comp)._renderedChildren[path.shift()];
}
return comp._instance;
};
window.$r = (node)=> getComponentById(node.getAttribute('data-reactid'))
실행하려면 Devtools를 열고 검사 할 요소를 강조 표시 한 다음 콘솔 유형에서 다음을 수행하십시오. $r($0)
React 16+ 버전 :
선택한 DOM 요소가 속한 가장 가까운 React 구성 요소 인스턴스를 원하는 경우 찾을 수있는 방법은 다음과 같습니다 ( @ Guan-Gui의 솔루션 에서 수정 됨 ).
window.getComponentFromElement = function(el) {
for (const key in el) {
if (key.startsWith('__reactInternalInstance$')) {
const fiberNode = el[key];
return fiberNode && fiberNode._debugOwner && fiberNode._debugOwner.stateNode;
}
}
return null;
};
여기서 트릭 은 DOM 요소가 속한 가장 가까운 구성 요소에 _debugOwner
대한 참조 인 속성 을 사용하는 것 FiberNode
입니다.
Caveat: Only running in dev mode will the components have the _debugOwner
property. This would not work in production mode.
Bonus
I created this handy snippet that you can run in your console so that you can click on any element and get the React component instance it belongs to.
document.addEventListener('click', function(event) {
const el = event.target;
for (const key in el) {
if (key.startsWith('__reactInternalInstance$')) {
const fiberNode = el[key];
const component = fiberNode && fiberNode._debugOwner;
if (component) {
console.log(component.type.displayName || component.type.name);
window.$r = component.stateNode;
}
return;
}
}
});
Install React devtools and use following, to access react element of corresponding dom node ($0).
for 0.14.8
var findReactNode = (node) =>Object.values(__REACT_DEVTOOLS_GLOBAL_HOOK__.helpers)[0]
.getReactElementFromNative(node)
._currentElement;
findReactNode($0);
Ofcourse, its a hack only..
I've adapted @Venryx's answer with a slightly adapted ES6 version that fit my needs. This helper function returns the current element instead of the _owner._instance property.
getReactDomComponent(dom) {
const internalInstance = dom[Object.keys(dom).find(key =>
key.startsWith('__reactInternalInstance$'))];
if (!internalInstance) return null;
return internalInstance._currentElement;
}
v15 and v16 compatible with svg, html, comment, text nodes
/* Node extends text, svg, html
usage for node $0:
$0.reactive // returns [node, parentNode, rootNode]
$0.react.props // {any:'prop'}
$0.react.setState(...) // update
*/
Object.defineProperties(Node.prototype, {
_react: {writable:true, value:''}
,reactKey: {
get: function(){
let symbol = this._react;
if(symbol){ return symbol; }
// v15, v16 use a string as key, probably a real symbol in the future
symbol = Object.keys(this).find(key => key.startsWith('__reactInternalInstance$'));
return Node.prototype._react = symbol || '';
}
}
// try to find the props/state/React-instance
,react: {
get: function(){
let react = this[ this.reactKey ] || null;
let $0;
if(react){
$0 = react._currentElement;
if($0){ // v15
if($0._owner){
return $0._owner._instance;
}else{
return $0;
};
}
$0 = react.return;
if($0){ // v16
// develop mode only: return react._debugOwner.stateNode
// both develop and prod modes:
return $0.stateNode
}
}else if(this._reactRootContainer){
// v16 _internalRoot === _internalRoot.current.stateNode
return this._reactRootContainer._internalRoot;
}
return react;
}
}
// make a list of self, ancestors that make up this branch of the tree
,reactive: {
get: function(list=[]){
let $0 = this;
while($0 && !$0[ $0.reactKey ] && !$0._reactRootContainer ){
$0 = $0.previousSibling;
};
if($0 && ($0[$0.reactKey] || $0._reactRootContainer)){
list.push($0);
};
$0 = this;
while($0 = $0.parentNode){
if($0[ $0.reactKey ] || $0._reactRootContainer){
list.push($0);
}
};
return list;
}
}
});
ReferenceURL : https://stackoverflow.com/questions/29321742/react-getting-a-component-from-a-dom-element-for-debugging
'Development Tip' 카테고리의 다른 글
Url.action ()을 사용하여 동적 자바 스크립트 값 전달 (0) | 2021.01.10 |
---|---|
특정 코드가 추가 된 커밋을 찾는 방법은 무엇입니까? (0) | 2021.01.09 |
Android Studio-레이아웃의 텍스트 및 디자인 미리보기보기 (0) | 2021.01.09 |
C #에서 얕은 복사를 수행하는 가장 빠른 방법 (0) | 2021.01.09 |
PHP CodeSniffer는 얼마나 유용합니까? (0) | 2021.01.09 |