Skip to content

Commit

Permalink
Merge pull request facebook#2629 from arnihermann/diff-msg-on-checksu…
Browse files Browse the repository at this point in the history
…m-fail

Give context aware message if markup reuse fails
  • Loading branch information
vjeux committed Dec 1, 2014
2 parents 5daffbb + a352b94 commit f5a9ea8
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
42 changes: 37 additions & 5 deletions src/browser/ui/ReactMount.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ if (__DEV__) {
// Used to store breadth-first search state in findComponentRoot.
var findComponentRootReusableArray = [];

/**
* Finds the index of the first character
* that's not common between the two given strings.
*
* @return {number} the index of the character where the strings diverge
*/
function firstDifferenceIndex(string1, string2) {
var minLen = Math.min(string1.length, string2.length);
for (var i = 0; i < minLen; i++) {
if (string1[i] !== string2[i]) {
return i;
}
}
return string1.length === string2.length ? -1 : minLen;
}

/**
* @param {DOMElement} container DOM element that may contain a React component.
* @return {?string} A "reactRoot" ID, if a React component is rendered.
Expand Down Expand Up @@ -719,11 +735,26 @@ var ReactMount = {
);

if (shouldReuseMarkup) {
if (ReactMarkupChecksum.canReuseMarkup(
markup,
getReactRootElementInContainer(container))) {
var rootElement = getReactRootElementInContainer(container);
if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {
return;
} else {
var checksum = rootElement.getAttribute(
ReactMarkupChecksum.CHECKSUM_ATTR_NAME
);
rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);

var rootMarkup = rootElement.outerHTML;
rootElement.setAttribute(
ReactMarkupChecksum.CHECKSUM_ATTR_NAME,
checksum
);

var diffIndex = firstDifferenceIndex(markup, rootMarkup);
var difference = ' (client) ' +
markup.substring(diffIndex - 20, diffIndex + 20) +
'\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);

invariant(
container.nodeType !== DOC_NODE_TYPE,
'You\'re trying to render a component to the document using ' +
Expand All @@ -733,7 +764,8 @@ var ReactMount = {
'methods are impure. React cannot handle this case due to ' +
'cross-browser quirks by rendering at the document root. You ' +
'should look for environment dependent code in your components ' +
'and ensure the props are the same client and server side.'
'and ensure the props are the same client and server side:\n' +
difference
);

if (__DEV__) {
Expand All @@ -745,7 +777,7 @@ var ReactMount = {
'new markup to compensate which works but you have lost many ' +
'of the benefits of server rendering. Instead, figure out ' +
'why the markup being generated is different on the client ' +
'or server.'
'or server:\n' + difference
);
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/browser/ui/__tests__/ReactRenderDocument-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ describe('rendering React components at document', function() {
'are impure. React cannot handle this case due to cross-browser ' +
'quirks by rendering at the document root. You should look for ' +
'environment dependent code in your components and ensure ' +
'the props are the same client and server side.'
'the props are the same client and server side:\n' +
' (client) data-reactid=".0.1">Hello world</body></\n' +
' (server) data-reactid=".0.1">Goodbye world</body>'
);
});

Expand Down

0 comments on commit f5a9ea8

Please sign in to comment.