diff --git a/src/renderers/shared/fiber/ReactFiberBeginWork.js b/src/renderers/shared/fiber/ReactFiberBeginWork.js index 2f80e30a52..cab153c112 100644 --- a/src/renderers/shared/fiber/ReactFiberBeginWork.js +++ b/src/renderers/shared/fiber/ReactFiberBeginWork.js @@ -163,6 +163,12 @@ module.exports = function(config : HostConfig, getSchedu updateQueue.isReplace = true; scheduleUpdate(fiber, updateQueue, LowPriority); }, + enqueueForceUpdate(instance) { + const fiber = ReactInstanceMap.get(instance); + const updateQueue = fiber.updateQueue || createUpdateQueue(null); + updateQueue.isForced = true; + scheduleUpdate(fiber, updateQueue, LowPriority); + }, enqueueCallback(instance, callback) { const fiber = ReactInstanceMap.get(instance); let updateQueue = fiber.updateQueue ? @@ -204,7 +210,8 @@ module.exports = function(config : HostConfig, getSchedu // The instance needs access to the fiber so that it can schedule updates ReactInstanceMap.set(instance, workInProgress); instance.updater = updater; - } else if (typeof instance.shouldComponentUpdate === 'function') { + } else if (typeof instance.shouldComponentUpdate === 'function' && + !(updateQueue && updateQueue.isForced)) { if (workInProgress.memoizedProps !== null) { // Reset the props, in case this is a ping-pong case rather than a // completed update case. For the completed update case, the instance diff --git a/src/renderers/shared/fiber/ReactFiberUpdateQueue.js b/src/renderers/shared/fiber/ReactFiberUpdateQueue.js index 97039994b1..aab252b655 100644 --- a/src/renderers/shared/fiber/ReactFiberUpdateQueue.js +++ b/src/renderers/shared/fiber/ReactFiberUpdateQueue.js @@ -21,6 +21,7 @@ type UpdateQueueNode = { export type UpdateQueue = UpdateQueueNode & { isReplace: boolean, + isForced: boolean, tail: UpdateQueueNode }; @@ -31,6 +32,7 @@ exports.createUpdateQueue = function(partialState : mixed) : UpdateQueue { callbackWasCalled: false, next: null, isReplace: false, + isForced: false, tail: (null : any), }; queue.tail = queue; diff --git a/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js b/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js index f3caa3d0a8..5213acfa48 100644 --- a/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js +++ b/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js @@ -682,4 +682,44 @@ describe('ReactIncremental', () => { ReactNoop.flush(); expect(instance.state).toEqual({ d: 'd' }); }); + + it('can forceUpdate', () => { + const ops = []; + + function Baz() { + ops.push('Baz'); + return
; + } + + let instance; + class Bar extends React.Component { + constructor() { + super(); + instance = this; + } + shouldComponentUpdate() { + return false; + } + render() { + ops.push('Bar'); + return ; + } + } + + function Foo() { + ops.push('Foo'); + return ( +
+ +
+ ); + } + + ReactNoop.render(); + ReactNoop.flush(); + expect(ops).toEqual(['Foo', 'Bar', 'Baz']); + instance.forceUpdate(); + ReactNoop.flush(); + expect(ops).toEqual(['Foo', 'Bar', 'Baz', 'Bar', 'Baz']); + }); });