Skip to content

Commit

Permalink
Warn When The HTML Mismatches in DEV (#10026)
Browse files Browse the repository at this point in the history
* Warn for text content

* Warn for different attributes/properties values

Warns if there are unknown extra attributes in the hydrated node.

It also tries to compare the existing property or attribute against the
expected value. It does this by reading the property and comparing it to
the prop. Except it's not that simple because multiple prop values can
yield the same output. For this we pass an extra expected value that is
a hint as to which one was used. This is a bit weird but I'm not sure the
alternatives were much better.

* Warn when there is an insertion or deletion during hydration

This warns if there is ever an insertion or deletion due to hydration
failing to find a match.

Currently we can't warn for insertions required into the root because
that's how we do all non-hydrating renders atm. Left a todo.

This strategy is a bit unfortunate that it leads to so much plumbing code.
And we have to add three extra methods to the HostConfig that are only used
in DEV and not for anything else. I don't really have a better idea.

* Don't try to delete children of a textarea

Textareas are special cases. The initial mount inserts children
as the default value, but we should leave that untouched. This is the same
as the special case where we set text content of children so I'll use that
mechanism.

* Change expected format for text differences

In Stack this is presented as HTML which needs to have normalized escaping
rules. In Fiber it is currently not presented as HTML but a raw string
so we don't escape it.

* Unmount component in between tests

In Fiber, the second warning isn't issued because it's considered an update
not a new initial render and we don't fire the warning for those.

* Change expectation of white space text behavior in Fiber

In Fiber we don't expect empty strings to be different from rendering null.
In fact, in a follow up I plan on formalizing this by never creating text
Fibers for empty strings.

* Warn for different dangerouslySetInnerHTML

We can't just compare the raw innerHTML value because it will have been
normalized. Instead, we'll create another element, set its innerHTML and
read it back.

Since there can be custom elements registered with this document, we want
to avoid any side-effects they might cause. So I do this in a fresh new
document.

I'm not sure how this would affect controlled components and other stuff
that could have changed after runtime. I think for those cases maybe we
just need a general way of opting out of the diff.
  • Loading branch information
sebmarkbage authored Jun 30, 2017
1 parent 9d13557 commit 8d61138
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 158 deletions.
149 changes: 0 additions & 149 deletions scripts/fiber/tests-passing-except-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,152 +3,3 @@ src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
* gives source code refs for unknown prop warning for exact elements (ssr)
* gives source code refs for unknown prop warning for exact elements in composition (ssr)
* should suggest property name if available (ssr)

src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js
* renders a blank div with client render on top of bad server markup
* renders a div with inline styles with client render on top of bad server markup
* renders a self-closing tag with client render on top of bad server markup
* renders a self-closing tag as a child with client render on top of bad server markup
* renders simple numbers with client render on top of bad server markup
* renders simple strings with client render on top of bad server markup
* renders string prop with true value with client render on top of bad server markup
* renders string prop with false value with client render on top of bad server markup
* renders boolean prop with true value with client render on top of bad server markup
* renders boolean prop with false value with client render on top of bad server markup
* renders boolean prop with self value with client render on top of bad server markup
* renders boolean prop with "" value with client render on top of bad server markup
* renders boolean prop with string value with client render on top of bad server markup
* renders boolean prop with array value with client render on top of bad server markup
* renders boolean prop with object value with client render on top of bad server markup
* renders boolean prop with non-zero number value with client render on top of bad server markup
* renders boolean prop with zero value with client render on top of bad server markup
* renders download prop with true value with client render on top of bad server markup
* renders download prop with false value with client render on top of bad server markup
* renders download prop with string value with client render on top of bad server markup
* renders download prop with string "true" value with client render on top of bad server markup
* renders className prop with string value with client render on top of bad server markup
* renders className prop with empty string value with client render on top of bad server markup
* renders className prop with true value with client render on top of bad server markup
* renders className prop with false value with client render on top of bad server markup
* renders htmlFor with string value with client render on top of bad server markup
* renders htmlFor with an empty string with client render on top of bad server markup
* renders className prop with true value with client render on top of bad server markup
* renders className prop with false value with client render on top of bad server markup
* renders no ref attribute with client render on top of bad server markup
* renders no children attribute with client render on top of bad server markup
* renders no key attribute with client render on top of bad server markup
* renders no dangerouslySetInnerHTML attribute with client render on top of bad server markup
* renders no unknown attributes with client render on top of bad server markup
* renders unknown data- attributes with client render on top of bad server markup
* renders no unknown attributes for non-standard elements with client render on top of bad server markup
* renders unknown attributes for custom elements with client render on top of bad server markup
* renders unknown attributes for custom elements using is with client render on top of bad server markup
* renders no HTML events with client render on top of bad server markup
* renders a div with text with client render on top of bad server markup
* renders a div with text with flanking whitespace with client render on top of bad server markup
* renders a div with an empty text child with client render on top of bad server markup
* renders a div with multiple empty text children with client render on top of bad server markup
* renders a div with multiple whitespace children with client render on top of bad server markup
* renders a div with text sibling to a node with client render on top of bad server markup
* renders a non-standard element with text with client render on top of bad server markup
* renders a custom element with text with client render on top of bad server markup
* renders a leading blank child with a text sibling with client render on top of bad server markup
* renders a trailing blank child with a text sibling with client render on top of bad server markup
* renders an element with two text children with client render on top of bad server markup
* renders a number as single child with client render on top of bad server markup
* renders zero as single child with client render on top of bad server markup
* renders an element with number and text children with client render on top of bad server markup
* renders null single child as blank with client render on top of bad server markup
* renders false single child as blank with client render on top of bad server markup
* renders undefined single child as blank with client render on top of bad server markup
* renders a null component children as empty with client render on top of bad server markup
* renders null children as blank with client render on top of bad server markup
* renders false children as blank with client render on top of bad server markup
* renders null and false children together as blank with client render on top of bad server markup
* renders only null and false children as blank with client render on top of bad server markup
* renders an svg element with client render on top of bad server markup
* renders svg element with an xlink with client render on top of bad server markup
* renders a math element with client render on top of bad server markup
* renders an img with client render on top of bad server markup
* renders a button with client render on top of bad server markup
* renders a div with dangerouslySetInnerHTML with client render on top of bad server markup
* renders a newline-eating tag with content not starting with \n with client render on top of bad server markup
* renders a newline-eating tag with content starting with \n with client render on top of bad server markup
* renders a normal tag with content starting with \n with client render on top of bad server markup
* renders stateless components with client render on top of bad server markup
* renders ES6 class components with client render on top of bad server markup
* renders factory components with client render on top of bad server markup
* renders single child hierarchies of components with client render on top of bad server markup
* renders multi-child hierarchies of components with client render on top of bad server markup
* renders a div with a child with client render on top of bad server markup
* renders a div with multiple children with client render on top of bad server markup
* renders a div with multiple children separated by whitespace with client render on top of bad server markup
* renders a div with a single child surrounded by whitespace with client render on top of bad server markup
* renders >,<, and & as single child with client render on top of bad server markup
* renders >,<, and & as multiple children with client render on top of bad server markup
* renders an input with a value and an onChange with client render on top of bad server markup
* renders an input with a value and readOnly with client render on top of bad server markup
* renders an input with a value and no onChange/readOnly with client render on top of bad server markup
* renders an input with a defaultValue with client render on top of bad server markup
* renders an input value overriding defaultValue with client render on top of bad server markup
* renders an input value overriding defaultValue no matter the prop order with client render on top of bad server markup
* renders a checkbox that is checked with an onChange with client render on top of bad server markup
* renders a checkbox that is checked with readOnly with client render on top of bad server markup
* renders a checkbox that is checked and no onChange/readOnly with client render on top of bad server markup
* renders a checkbox with defaultChecked with client render on top of bad server markup
* renders a checkbox checked overriding defaultChecked with client render on top of bad server markup
* renders a checkbox checked overriding defaultChecked no matter the prop order with client render on top of bad server markup
* renders a textarea with a value and an onChange with client render on top of bad server markup
* renders a textarea with a value and readOnly with client render on top of bad server markup
* renders a textarea with a value and no onChange/readOnly with client render on top of bad server markup
* renders a textarea with a defaultValue with client render on top of bad server markup
* renders a textarea value overriding defaultValue with client render on top of bad server markup
* renders a textarea value overriding defaultValue no matter the prop order with client render on top of bad server markup
* renders a select with a value and an onChange with client render on top of bad server markup
* renders a select with a value and readOnly with client render on top of bad server markup
* renders a select with a multiple values and an onChange with client render on top of bad server markup
* renders a select with a multiple values and readOnly with client render on top of bad server markup
* renders a select with a value and no onChange/readOnly with client render on top of bad server markup
* renders a select with a defaultValue with client render on top of bad server markup
* renders a select value overriding defaultValue with client render on top of bad server markup
* renders a select value overriding defaultValue no matter the prop order with client render on top of bad server markup
* renders a controlled text input with client render on top of bad server markup
* renders a controlled textarea with client render on top of bad server markup
* renders a controlled checkbox with client render on top of bad server markup
* renders a controlled select with client render on top of bad server markup
* renders class child with context with client render on top of bad server markup
* renders stateless child with context with client render on top of bad server markup
* renders class child without context with client render on top of bad server markup
* renders stateless child without context with client render on top of bad server markup
* renders class child with wrong context with client render on top of bad server markup
* renders stateless child with wrong context with client render on top of bad server markup
* renders with context passed through to a grandchild with client render on top of bad server markup
* renders a child context overriding a parent context with client render on top of bad server markup
* renders a child context merged with a parent context with client render on top of bad server markup
* renders with a call to componentWillMount before getChildContext with client render on top of bad server markup
* should error reconnecting different element types
* should error reconnecting missing attributes
* should error reconnecting added attributes
* should error reconnecting different attribute values
* should error reconnecting different text
* should error reconnecting different numbers
* should error reconnecting different number from text
* should error reconnecting different text in two code blocks
* should error reconnecting missing children
* should error reconnecting added children
* should error reconnecting more children
* should error reconnecting fewer children
* should error reconnecting reordered children
* should error reconnecting a div with children separated by whitespace on the client
* should error reconnecting a div with children separated by different whitespace on the server
* should error reconnecting a div with children separated by different whitespace
* can distinguish an empty component from a dom node
* can distinguish an empty component from an empty text component
* should error reconnecting a div with different dangerouslySetInnerHTML

src/renderers/dom/shared/__tests__/ReactMount-test.js
* should warn if mounting into dirty rendered markup
* should account for escaping on a checksum mismatch

src/renderers/dom/shared/__tests__/ReactServerRendering-test.js
* should have the correct mounting behavior
Loading

0 comments on commit 8d61138

Please sign in to comment.