forceUpdate

Adds a field to the update queue that causes shouldComponentUpdate to
be skipped.
This commit is contained in:
Andrew Clark
2016-09-13 15:26:48 -07:00
committed by Sebastian Markbage
parent d8c24cfa78
commit f514662ca0
3 changed files with 50 additions and 1 deletions
@@ -163,6 +163,12 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>, 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<T, P, I, C>(config : HostConfig<T, P, I, C>, 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
@@ -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;
@@ -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 <div />;
}
let instance;
class Bar extends React.Component {
constructor() {
super();
instance = this;
}
shouldComponentUpdate() {
return false;
}
render() {
ops.push('Bar');
return <Baz />;
}
}
function Foo() {
ops.push('Foo');
return (
<div>
<Bar />
</div>
);
}
ReactNoop.render(<Foo />);
ReactNoop.flush();
expect(ops).toEqual(['Foo', 'Bar', 'Baz']);
instance.forceUpdate();
ReactNoop.flush();
expect(ops).toEqual(['Foo', 'Bar', 'Baz', 'Bar', 'Baz']);
});
});