From 59c94648c485b60035e150fc5e79232c4d25960f Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Wed, 26 Oct 2016 16:56:46 -0700 Subject: [PATCH] PureComponent in Fiber Passes existing PureComponent tests --- .../shared/fiber/ReactFiberClassComponent.js | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/renderers/shared/fiber/ReactFiberClassComponent.js b/src/renderers/shared/fiber/ReactFiberClassComponent.js index 4a8c27308b041..2211dead1876f 100644 --- a/src/renderers/shared/fiber/ReactFiberClassComponent.js +++ b/src/renderers/shared/fiber/ReactFiberClassComponent.js @@ -25,6 +25,7 @@ var { } = require('ReactFiberUpdateQueue'); var { isMounted } = require('ReactFiberTreeReflection'); var ReactInstanceMap = require('ReactInstanceMap'); +var shallowEqual = require('shallowEqual'); module.exports = function(scheduleUpdate : (fiber: Fiber, priorityLevel : PriorityLevel) => void) { @@ -73,6 +74,28 @@ module.exports = function(scheduleUpdate : (fiber: Fiber, priorityLevel : Priori }, }; + function checkShouldComponentUpdate(workInProgress, oldProps, newProps, newState) { + const updateQueue = workInProgress.updateQueue; + if (oldProps === null || (updateQueue && updateQueue.isForced)) { + return true; + } + + const instance = workInProgress.stateNode; + if (typeof instance.shouldComponentUpdate === 'function') { + return instance.shouldComponentUpdate(newProps, newState); + } + + const type = workInProgress.type; + if (type.prototype && type.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || + !shallowEqual(instance.state, newState) + ); + } + + return true; + } + function adoptClassInstance(workInProgress : Fiber, instance : any) : void { instance.updater = updater; workInProgress.stateNode = instance; @@ -116,7 +139,6 @@ module.exports = function(scheduleUpdate : (fiber: Fiber, priorityLevel : Priori // Called on a preexisting class instance. Returns false if a resumed render // could be reused. function resumeMountClassInstance(workInProgress : Fiber) : boolean { - const instance = workInProgress.stateNode; let newState = workInProgress.memoizedState; let newProps = workInProgress.pendingProps; if (!newProps) { @@ -132,13 +154,12 @@ module.exports = function(scheduleUpdate : (fiber: Fiber, priorityLevel : Priori // componentWillMount and before this componentWillMount? Probably // unsupported anyway. - const updateQueue = workInProgress.updateQueue; - - // If this completed, we might be able to just reuse this instance. - if (typeof instance.shouldComponentUpdate === 'function' && - !(updateQueue && updateQueue.isForced) && - workInProgress.memoizedProps !== null && - !instance.shouldComponentUpdate(newProps, newState)) { + if (!checkShouldComponentUpdate( + workInProgress, + workInProgress.memoizedProps, + newProps, + newState + )) { return false; } @@ -196,10 +217,12 @@ module.exports = function(scheduleUpdate : (fiber: Fiber, priorityLevel : Priori newState = previousState; } - if (typeof instance.shouldComponentUpdate === 'function' && - !(updateQueue && updateQueue.isForced) && - oldProps !== null && - !instance.shouldComponentUpdate(newProps, newState)) { + if (!checkShouldComponentUpdate( + workInProgress, + oldProps, + newProps, + newState + )) { // TODO: Should this get the new props/state updated regardless? return false; }