Handle Bailed Out HostText update and MultiChildText test (#8371)
This handles the case where a host text bails out. In that case we need to reuse its previous memoizedProps. We should also only schedule an actual update if it did actually change its text content. I updated the unit test to ignore comment nodes if we're using Fiber.
Sebastian Markbåge committed
Nov 28, 2016 at 17:26 UTC
f634b813e121d1d81d8fbd5007990e8e59824491
2 files changed
+41
-22
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+14
-3
@@ -249,9 +249,20 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
249
case HostText:
250
let newText = workInProgress.pendingProps;
251
if (current && workInProgress.stateNode != null) {
252
- // If we have an alternate, that means this is an update and we need to
253
- // schedule a side-effect to do the updates.
254
- markUpdate(workInProgress);
252
+ const oldText = current.memoizedProps;
253
+ if (newText === null) {
254
+ // If this was a bail out we need to fall back to memoized text.
255
+ // This works the same way as HostComponent.
256
+ newText = workInProgress.memoizedProps;
257
+ if (newText === null) {
258
+ newText = oldText;
259
+ }
260
+ }
261
+ // If we have an alternate, that means this is an update and we need
262
+ // to schedule a side-effect to do the updates.
263
+ if (oldText !== newText) {
264
+ markUpdate(workInProgress);
265
+ }
266
} else {
267
if (typeof newText !== 'string') {
268
if (workInProgress.stateNode === null) {
src/renderers/shared/shared/__tests__/ReactMultiChildText-test.js
+27
-19
@@ -13,6 +13,7 @@
13
14
var React = require('React');
15
var ReactDOM = require('ReactDOM');
16
+var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
17
var ReactTestUtils = require('ReactTestUtils');
18
19
// Helpers
@@ -57,28 +58,35 @@ var expectChildren = function(container, children) {
58
var child = children[i];
59
60
if (typeof child === 'string') {
60
- openingCommentNode = outerNode.childNodes[mountIndex];
61
-
62
- expect(openingCommentNode.nodeType).toBe(8);
63
- expect(openingCommentNode.nodeValue).toMatch(/ react-text: [0-9]+ /);
64
-
65
- if (child === '') {
66
- textNode = null;
67
- closingCommentNode = openingCommentNode.nextSibling;
68
- mountIndex += 2;
69
- } else {
70
- textNode = openingCommentNode.nextSibling;
71
- closingCommentNode = textNode.nextSibling;
72
- mountIndex += 3;
73
- }
74
-
75
- if (textNode) {
61
+ if (ReactDOMFeatureFlags.useFiber) {
62
+ textNode = outerNode.childNodes[mountIndex];
63
expect(textNode.nodeType).toBe(3);
64
expect(textNode.data).toBe('' + child);
65
+ mountIndex++;
66
+ } else {
67
+ openingCommentNode = outerNode.childNodes[mountIndex];
68
+
69
+ expect(openingCommentNode.nodeType).toBe(8);
70
+ expect(openingCommentNode.nodeValue).toMatch(/ react-text: [0-9]+ /);
71
+
72
+ if (child === '') {
73
+ textNode = null;
74
+ closingCommentNode = openingCommentNode.nextSibling;
75
+ mountIndex += 2;
76
+ } else {
77
+ textNode = openingCommentNode.nextSibling;
78
+ closingCommentNode = textNode.nextSibling;
79
+ mountIndex += 3;
80
+ }
81
+
82
+ if (textNode) {
83
+ expect(textNode.nodeType).toBe(3);
84
+ expect(textNode.data).toBe('' + child);
85
+ }
86
+
87
+ expect(closingCommentNode.nodeType).toBe(8);
88
+ expect(closingCommentNode.nodeValue).toBe(' /react-text ');
89
}
79
-
80
- expect(closingCommentNode.nodeType).toBe(8);
81
- expect(closingCommentNode.nodeValue).toBe(' /react-text ');
90
} else {
91
var elementDOMNode = outerNode.childNodes[mountIndex];
92
expect(elementDOMNode.tagName).toBe('DIV');