You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using React v15.3.2 and ReactServer.renderToString but I'm reasonably sure the behaviour is the same with ReactDOM (and I've not seen anything in the release notes of 15.4 regarding improved error messages from render).
The problem is of course that the source of the stack-trace is simply the originating render or renderToString call. In certain occasions the error messages includes the name of a component class whose render() method to check, but even that is not terribly useful for larger components.
I understand there are limitations to how much debug information can tag along element creation code during normal operation, but might it not be practical to simply re-render and re-check (using more heavy-weight tracing) a faulty call to createElement after the error already happened?
Here is a proof of concept (which works great and has been very helpful):
letchildContextMap=newWeakMap();letfindInvalidElement=(el,path,ctx)=>{// console.log('-path', path)if(el===null||typeofel==='undefined'||typeofel==='boolean'||typeofel==='string'){return;}if(Array.isArray(el)){for(let[idx,item]ofel.entries()){findInvalidElement(item,`${path}[${idx}]`,ctx);}return;}if(!(typeofel.type==='function'||typeofel.type==='string')){console.warn('/!\\ INVALID ELEMENT TYPE FOUND /!\\');console.warn(`At: ${path}`);console.warn('Type:',el.type);}if(childContextMap.has(el)){ctx=childContextMap.get(el);}if(typeofel.type==='function'){if(el.type.prototypeinstanceofReact.Component){letelement=new(el.type)(el.props,ctx);letchildContext={};if(typeofelement.getChildContext==='function'){childContext=Object.assign({},ctx,element.getChildContext());React.Children.forEach(el.props.children,child=>{childContextMap.set(child,childContext);});}findInvalidElement(element.render(),`${path}${el.type.displayName||el.type.name||el.type}.render()->`,ctx);}else{findInvalidElement(el.type(el.props,ctx),`${path}${el.type.displayName||el.type.name||el.type}()->`,ctx);}}elseif(el.props&&el.props.children){letidx=0;React.Children.forEach(el.props.children,child=>{findInvalidElement(child,`${path}${idx}:${el.type.name||el.type}/`,ctx);idx++;});}};
It's just a quick kludged-together element-tree renderer that tracks the 'path' to each individual node in the tree (and is thus able to report it if the type is incorrect). Together with the stack trace this allows for exact identification of the faulty node.
Using React v15.3.2 and
ReactServer.renderToString
but I'm reasonably sure the behaviour is the same withReactDOM
(and I've not seen anything in the release notes of 15.4 regarding improved error messages from render).The problem is of course that the source of the stack-trace is simply the originating
render
orrenderToString
call. In certain occasions the error messages includes the name of a component class whoserender()
method to check, but even that is not terribly useful for larger components.I understand there are limitations to how much debug information can tag along element creation code during normal operation, but might it not be practical to simply re-render and re-check (using more heavy-weight tracing) a faulty call to
createElement
after the error already happened?Here is a proof of concept (which works great and has been very helpful):
It's just a quick kludged-together element-tree renderer that tracks the 'path' to each individual node in the tree (and is thus able to report it if the type is incorrect). Together with the stack trace this allows for exact identification of the faulty node.
For example, the path:
Main.render()->Provider.render()->IntlProvider.render()->1:div/0:div/ReactCSSTransitionGroup.render()->ReactTransitionGroup.render()->0:span/ReactCSSTransitionGroupChild.render()->0:div/0:div/Connect(Connect(ExampleForm)).render()->Connect(ExampleForm).render()->ExampleForm.render()->3:form/ExampleSubForm.render()->3:div/
Though verbose, it can be followed without ambiguity:
render()
method ofMain
render()
method ofProvider
render()
method ofIntlProvider
1
) child (adiv
)0
) child (adiv
)render()
method ofReactCSSTransitionGroup
render()
method ofReactTransitionGroup
0
) child (aspan
)render()
method ofReactCSSTransitionGroupChild
0
) child (adiv
)0
) child (adiv
)The text was updated successfully, but these errors were encountered: