Skip to content

Commit 2a370e8

Browse files
egorshulgajoshwcomeau
authored andcommitted
Increasing performance by avoiding styles recalculations (#211)
* Split DOM reads and writes to be performed in batches to avoid styles recalculations. * Cosmetics
1 parent 34d455b commit 2a370e8

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

src/FlipMove.js

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,14 @@ class FlipMove extends Component<ConvertedProps, FlipMoveState> {
213213
this.doesChildNeedToBeAnimated,
214214
);
215215

216-
dynamicChildren.forEach((child, n) => {
216+
// Splitting DOM reads and writes to be peformed in batches
217+
const childrenInitialStyles = dynamicChildren.map(child =>
218+
this.computeInitialStyles(child),
219+
);
220+
dynamicChildren.forEach((child, index) => {
217221
this.remainingAnimations += 1;
218222
this.childrenToAnimate.push(getKey(child));
219-
this.animateChild(child, n);
223+
this.animateChild(child, index, childrenInitialStyles[index]);
220224
});
221225

222226
if (typeof this.props.onStartAll === 'function') {
@@ -382,7 +386,7 @@ class FlipMove extends Component<ConvertedProps, FlipMoveState> {
382386
});
383387
}
384388

385-
animateChild(child: ChildData, index: number) {
389+
animateChild(child: ChildData, index: number, childInitialStyles: Styles) {
386390
const { domNode } = this.getChildData(getKey(child));
387391
if (!domNode) {
388392
return;
@@ -396,7 +400,7 @@ class FlipMove extends Component<ConvertedProps, FlipMoveState> {
396400
// In FLIP terminology, this is the 'Invert' stage.
397401
applyStylesToDOMNode({
398402
domNode,
399-
styles: this.computeInitialStyles(child),
403+
styles: childInitialStyles,
400404
});
401405

402406
// Start by invoking the onStart callback for this child.
@@ -553,19 +557,24 @@ class FlipMove extends Component<ConvertedProps, FlipMoveState> {
553557

554558
this.parentData.boundingBox = this.props.getPosition(parentDomNode);
555559

560+
// Splitting DOM reads and writes to be peformed in batches
561+
const childrenBoundingBoxes = [];
562+
556563
this.state.children.forEach(child => {
557564
const childKey = getKey(child);
558565

559566
// It is possible that a child does not have a `key` property;
560567
// Ignore these children, they don't need to be moved.
561568
if (!childKey) {
569+
childrenBoundingBoxes.push(null);
562570
return;
563571
}
564572

565573
// In very rare circumstances, for reasons unknown, the ref is never
566574
// populated for certain children. In this case, avoid doing this update.
567575
// see: https://github.com/joshwcomeau/react-flip-move/pull/91
568576
if (!this.hasChildData(childKey)) {
577+
childrenBoundingBoxes.push(null);
569578
return;
570579
}
571580

@@ -574,15 +583,30 @@ class FlipMove extends Component<ConvertedProps, FlipMoveState> {
574583
// If the child element returns null, we need to avoid trying to
575584
// account for it
576585
if (!childData.domNode || !child) {
586+
childrenBoundingBoxes.push(null);
577587
return;
578588
}
579589

580-
this.setChildData(childKey, {
581-
boundingBox: getRelativeBoundingBox({
590+
childrenBoundingBoxes.push(
591+
getRelativeBoundingBox({
582592
childDomNode: childData.domNode,
583593
parentDomNode,
584594
getPosition: this.props.getPosition,
585595
}),
596+
);
597+
});
598+
599+
this.state.children.forEach((child, index) => {
600+
const childKey = getKey(child);
601+
602+
const childBoundingBox = childrenBoundingBoxes[index];
603+
604+
if (!childKey) {
605+
return;
606+
}
607+
608+
this.setChildData(childKey, {
609+
boundingBox: childBoundingBox,
586610
});
587611
});
588612
}

0 commit comments

Comments
 (0)