Enable text updates in ReactNoop
We'll enable updating of text nodes. To be able to test that we need the text nodes to be mutable. They're currently just strings in the Noop renderer so this makes them an object instead. That exposed a bug in ReactFiberCommitWork for text nodes.
Sebastian Markbage committed
Sep 19, 2016 at 15:26 UTC
13f01be64f92b3c9a693b40506c4c2972ccfe4eb
3 files changed
+14
-11
src/renderers/noop/ReactNoop.js
+10
-6
@@ -32,11 +32,12 @@ var scheduledAnimationCallback = null;
32
var scheduledDeferredCallback = null;
33
34
const TERMINAL_TAG = 99;
35
+const TEXT_TAG = 98;
36
37
type Container = { rootID: number, children: Array<Instance | TextInstance> };
38
type Props = { prop: any };
39
type Instance = { tag: 99, type: string, id: number, children: Array<Instance | TextInstance>, prop: any };
39
-type TextInstance = string;
40
+type TextInstance = { tag: 98, text: string };
41
42
var instanceCounter = 0;
43
@@ -44,7 +45,7 @@ function recursivelyAppendChildren(flatArray : Array<Instance | TextInstance>, c
45
if (!child) {
46
return;
47
}
47
- if (typeof child === 'string' || child.tag === TERMINAL_TAG) {
48
+ if (child.tag === TERMINAL_TAG || child.tag === TEXT_TAG) {
49
flatArray.push(child);
50
} else {
51
let node = child;
@@ -93,11 +94,14 @@ var NoopRenderer = ReactFiberReconciler({
94
},
95
96
createTextInstance(text : string) : TextInstance {
96
- return text;
97
+ var inst = { tag: TEXT_TAG, text : text };
98
+ // Hide from unit tests
99
+ Object.defineProperty(inst, 'tag', { value: inst.tag, enumerable: false });
100
+ return inst;
101
},
102
103
commitTextUpdate(textInstance : TextInstance, oldText : string, newText : string) : void {
100
- // Not yet supported.
104
+ textInstance.text = newText;
105
},
106
107
scheduleAnimationCallback(callback) {
@@ -178,8 +182,8 @@ var ReactNoop = {
182
function logHostInstances(children: Array<Instance | TextInstance>, depth) {
183
for (var i = 0; i < children.length; i++) {
184
var child = children[i];
181
- if (typeof child === 'string') {
182
- log(' '.repeat(depth) + '- ' + child);
185
+ if (child.tag === TEXT_TAG) {
186
+ log(' '.repeat(depth) + '- ' + child.text);
187
} else {
188
log(' '.repeat(depth) + '- ' + child.type + '#' + child.id);
189
logHostInstances(child.children, depth + 1);
src/renderers/shared/fiber/ReactFiberCommitWork.js
+3
-5
@@ -74,13 +74,11 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
74
if (finishedWork.stateNode == null || !current) {
75
throw new Error('This should only be done during updates.');
76
}
77
- // TODO: This never gets called yet because I don't have update support
78
- // for text nodes. This only gets updated through a host component or
79
- // container updating with this as one of its child nodes.
77
const textInstance : TI = finishedWork.stateNode;
81
- const oldText : string = finishedWork.memoizedProps;
82
- const newText : string = current.memoizedProps;
78
+ const newText : string = finishedWork.memoizedProps;
79
+ const oldText : string = current.memoizedProps;
80
commitTextUpdate(textInstance, oldText, newText);
81
+ return;
82
}
83
default:
84
throw new Error('This unit of work tag should not have side-effects.');
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
+1
@@ -21,6 +21,7 @@ describe('ReactIncrementalSideEffects', () => {
21
});
22
23
function div(...children) {
24
+ children = children.map(c => typeof c === 'string' ? { text: c } : c);
25
return { type: 'div', children, prop: undefined };
26
}
27