-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate DOM nesting when possible #3310
Comments
I think that this would be very useful IFF we had a shared data source between React and this plugin, that matched what browsers accepted. Do you know of one? |
There's this file from the React source here: https://github.com/facebook/react/blob/main/packages/react-dom/src/client/validateDOMNesting.js (apparently Sophie extracted a subset of the spec, Dan mentioned) Maybe that plus some additional rules for common things? |
Is that reachable from the actual npm package? |
Seems like |
If we can access them from react, that’d be sufficient, but we’d have to be able to do so across many react versions :-/ |
Ah looks like there is an ESLint plugin from @MananTank that does this over here 👀 This is based on |
WorkaroundUsing some of the original (This has also been released as part of
/** @type {import('@typescript-eslint/utils').TSESLint.Linter.Config} */
const config = {
rules: {
'no-restricted-syntax': [
'warn',
// Warn on nesting <a> elements, <button> elements and framework <Link> components inside of each other
{
selector:
"JSXElement[openingElement.name.name='a'] > JSXElement[openingElement.name.name=/^a|button|Link$/]",
message:
'Invalid DOM Nesting: anchor elements cannot have anchor elements, button elements or Link components as children',
},
{
selector:
"JSXElement[openingElement.name.name='button'] > JSXElement[openingElement.name.name=/^a|button|Link$/]",
message:
'Invalid DOM Nesting: button elements cannot have anchor elements, button elements or Link components as children',
},
{
selector:
"JSXElement[openingElement.name.name='Link'] > JSXElement[openingElement.name.name=/^a|button|Link$/]",
message:
'Invalid DOM Nesting: Link components cannot have anchor elements, button elements or Link components as children',
},
// Warn on nesting of non-<li> elements inside of <ol> and <ul> elements
{
selector:
"JSXElement[openingElement.name.name=/^ol|ul$/] > JSXElement[openingElement.name.name!='li'][openingElement.name.name!=/^[A-Z]/]",
message:
'Invalid DOM Nesting: ol and ul elements cannot have non-li elements as children',
},
// Warn on nesting common invalid elements inside of <p> elements
{
selector:
"JSXElement[openingElement.name.name='p'] > JSXElement[openingElement.name.name=/^div|h1|h2|h3|h4|h5|h6|hr|ol|p|table|ul$/]",
message:
'Invalid DOM Nesting: p elements cannot have div, h1, h2, h3, h4, h5, h6, hr, ol, p, table or ul elements as children',
},
// Warn on nesting any invalid elements inside of <table> elements
{
selector:
"JSXElement[openingElement.name.name='table'] > JSXElement[openingElement.name.name!=/^caption|colgroup|tbody|tfoot|thead$/][openingElement.name.name!=/^[A-Z]/]",
message:
'Invalid DOM Nesting: table elements cannot have element which are not caption, colgroup, tbody, tfoot or thead elements as children',
},
// Warn on nesting any invalid elements inside of <tbody>, <thead> and <tfoot> elements
{
selector:
"JSXElement[openingElement.name.name=/tbody|thead|tfoot/] > JSXElement[openingElement.name.name!='tr'][openingElement.name.name!=/^[A-Z]/]",
message:
'Invalid DOM Nesting: tbody, thead and tfoot elements cannot have non-tr elements as children',
},
// Warn on nesting any invalid elements inside of <tr> elements
{
selector:
"JSXElement[openingElement.name.name='tr'] > JSXElement[openingElement.name.name!=/th|td/][openingElement.name.name!=/^[A-Z]/]",
message:
'Invalid DOM Nesting: tr elements cannot have elements which are not th or td elements as children',
},
},
};
module.exports = config; This handles the things we see that students most commonly need:
Looks like this on some invalid code: |
That's a great POC for a new rule! I'd love to see a PR that adds it, with lots of test cases :-D |
@ljharb Hello, I notice this PR is still open. what is required to get it to completion and merged into the package? I ran into some |
@adeleke5140 this isn’t a PR, so what’s required is “a PR” :-) |
@adeleke5140 if you'd like to create a PR for this to get it into Here are some potentially useful links:
|
Hey @ljharb, long time no see! 👋 Have been pretty inactive around here, sorry about that! Lots of new students.
Wanted to see what you think about a new feature to validate DOM nesting when possible, to avoid such errors as seen below - which now, as of React 18, lead to hydration errors.
Problem:
th
is not a valid child oftfoot
I remember React did some kind of simple validation of DOM nesting, although I haven't seen this error for a while now (maybe just haven't run into it any more).
Maybe
eslint-plugin-react
could have some simple JSX validation (maybe based on a well-maintained library). Not across component boundaries or anything, only simple React elements which are HTML tags.It leads to this (pretty confusing) error with latest Next.js (see this StackBlitz):
If you were to open the DevTools and scroll up all the way to the top, you would see a more helpful error message (which, arguably, React should also display), but it's pretty hidden. Also, it's a confusing error message for those unfamiliar with the finer details of HTML or how React creates nodes:
The text was updated successfully, but these errors were encountered: