@samitouri / QOS-React / commits / f514662ca0

forceUpdate

Adds a field to the update queue that causes shouldComponentUpdate to be skipped.

Andrew Clark committed Aug 4, 2016 at 19:16 UTC f514662ca0959fd42031396c5c21dc3241abbf66
3 files changed +50 -1
src/renderers/shared/fiber/ReactFiberBeginWork.js
+8 -1
@@ -163,6 +163,12 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>, getSchedu
163 updateQueue.isReplace = true;
164 scheduleUpdate(fiber, updateQueue, LowPriority);
165 },
166 + enqueueForceUpdate(instance) {
167 + const fiber = ReactInstanceMap.get(instance);
168 + const updateQueue = fiber.updateQueue || createUpdateQueue(null);
169 + updateQueue.isForced = true;
170 + scheduleUpdate(fiber, updateQueue, LowPriority);
171 + },
172 enqueueCallback(instance, callback) {
173 const fiber = ReactInstanceMap.get(instance);
174 let updateQueue = fiber.updateQueue ?
@@ -204,7 +210,8 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>, getSchedu
210 // The instance needs access to the fiber so that it can schedule updates
211 ReactInstanceMap.set(instance, workInProgress);
212 instance.updater = updater;
207 - } else if (typeof instance.shouldComponentUpdate === 'function') {
213 + } else if (typeof instance.shouldComponentUpdate === 'function' &&
214 + !(updateQueue && updateQueue.isForced)) {
215 if (workInProgress.memoizedProps !== null) {
216 // Reset the props, in case this is a ping-pong case rather than a
217 // completed update case. For the completed update case, the instance
src/renderers/shared/fiber/ReactFiberUpdateQueue.js
+2
@@ -21,6 +21,7 @@ type UpdateQueueNode = {
21
22 export type UpdateQueue = UpdateQueueNode & {
23 isReplace: boolean,
24 + isForced: boolean,
25 tail: UpdateQueueNode
26 };
27
@@ -31,6 +32,7 @@ exports.createUpdateQueue = function(partialState : mixed) : UpdateQueue {
32 callbackWasCalled: false,
33 next: null,
34 isReplace: false,
35 + isForced: false,
36 tail: (null : any),
37 };
38 queue.tail = queue;
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+40
@@ -682,4 +682,44 @@ describe('ReactIncremental', () => {
682 ReactNoop.flush();
683 expect(instance.state).toEqual({ d: 'd' });
684 });
685 +
686 + it('can forceUpdate', () => {
687 + const ops = [];
688 +
689 + function Baz() {
690 + ops.push('Baz');
691 + return <div />;
692 + }
693 +
694 + let instance;
695 + class Bar extends React.Component {
696 + constructor() {
697 + super();
698 + instance = this;
699 + }
700 + shouldComponentUpdate() {
701 + return false;
702 + }
703 + render() {
704 + ops.push('Bar');
705 + return <Baz />;
706 + }
707 + }
708 +
709 + function Foo() {
710 + ops.push('Foo');
711 + return (
712 + <div>
713 + <Bar />
714 + </div>
715 + );
716 + }
717 +
718 + ReactNoop.render(<Foo />);
719 + ReactNoop.flush();
720 + expect(ops).toEqual(['Foo', 'Bar', 'Baz']);
721 + instance.forceUpdate();
722 + ReactNoop.flush();
723 + expect(ops).toEqual(['Foo', 'Bar', 'Baz', 'Bar', 'Baz']);
724 + });
725 });