@samitouri / QOS-React / commits / d8c24cfa78

replaceState

Adds a field to UpdateQueue that indicates whether an update should replace the previous state completely.

Andrew Clark committed Aug 4, 2016 at 18:55 UTC d8c24cfa78bd00691bf20dc1ad2750de84dd8ad4
3 files changed +39 -2
src/renderers/shared/fiber/ReactFiberBeginWork.js
+6
@@ -157,6 +157,12 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>, getSchedu
157 createUpdateQueue(partialState);
158 scheduleUpdate(fiber, updateQueue, LowPriority);
159 },
160 + enqueueReplaceState(instance, state) {
161 + const fiber = ReactInstanceMap.get(instance);
162 + const updateQueue = createUpdateQueue(state);
163 + updateQueue.isReplace = true;
164 + scheduleUpdate(fiber, updateQueue, LowPriority);
165 + },
166 enqueueCallback(instance, callback) {
167 const fiber = ReactInstanceMap.get(instance);
168 let updateQueue = fiber.updateQueue ?
src/renderers/shared/fiber/ReactFiberUpdateQueue.js
+4 -2
@@ -20,6 +20,7 @@ type UpdateQueueNode = {
20 };
21
22 export type UpdateQueue = UpdateQueueNode & {
23 + isReplace: boolean,
24 tail: UpdateQueueNode
25 };
26
@@ -29,6 +30,7 @@ exports.createUpdateQueue = function(partialState : mixed) : UpdateQueue {
30 callback: null,
31 callbackWasCalled: false,
32 next: null,
33 + isReplace: false,
34 tail: (null : any),
35 };
36 queue.tail = queue;
@@ -69,7 +71,7 @@ exports.callCallbacks = function(queue : UpdateQueue, context : any) {
71
72 exports.mergeUpdateQueue = function(queue : UpdateQueue, prevState : any, props : any) : any {
73 let node : ?UpdateQueueNode = queue;
72 - let state = Object.assign({}, prevState);
74 + let state = queue.isReplace ? null : Object.assign({}, prevState);
75 while (node) {
76 let partialState;
77 if (typeof node.partialState === 'function') {
@@ -78,7 +80,7 @@ exports.mergeUpdateQueue = function(queue : UpdateQueue, prevState : any, props
80 } else {
81 partialState = node.partialState;
82 }
81 - state = Object.assign(state, partialState);
83 + state = Object.assign(state || {}, partialState);
84 node = node.next;
85 }
86 return state;
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+29
@@ -653,4 +653,33 @@ describe('ReactIncremental', () => {
653 ReactNoop.flush();
654 expect(instance.state.num).toEqual(6);
655 });
656 +
657 + it('can replaceState', () => {
658 + let instance;
659 + const Bar = React.createClass({
660 + getInitialState() {
661 + instance = this;
662 + return { a: 'a' };
663 + },
664 + render() {
665 + return <div>{this.props.children}</div>;
666 + },
667 + });
668 +
669 + function Foo() {
670 + return (
671 + <div>
672 + <Bar />
673 + </div>
674 + );
675 + }
676 +
677 + ReactNoop.render(<Foo />);
678 + ReactNoop.flush();
679 + instance.setState({ b: 'b' });
680 + instance.setState({ c: 'c' });
681 + instance.replaceState({ d: 'd' });
682 + ReactNoop.flush();
683 + expect(instance.state).toEqual({ d: 'd' });
684 + });
685 });