Skip to content

Commit

Permalink
Merge pull request #1462 from FormidableLabs/experiment/animation-wit…
Browse files Browse the repository at this point in the history
…h-new-context

New context API
  • Loading branch information
boygirl authored Dec 20, 2019
2 parents a242c84 + ff907f4 commit c8090c6
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 125 deletions.
2 changes: 2 additions & 0 deletions packages/victory-core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ export { default as Text } from "./victory-primitives/text";
export { default as CommonProps } from "./victory-util/common-props";
export { default as Wrapper } from "./victory-util/wrapper";
export { default as Axis } from "./victory-util/axis";
export { default as TimerContext } from "./victory-util/timer-context";
export { default as PortalContext } from "./victory-portal/portal-context";
37 changes: 11 additions & 26 deletions packages/victory-core/src/victory-animation/victory-animation.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import PropTypes from "prop-types";
import * as d3Ease from "d3-ease";
import { victoryInterpolator } from "./util";
import Timer from "../victory-util/timer";
import TimerContext from "../victory-util/timer-context";
import isEqual from "react-fast-compare";

export default class VictoryAnimation extends React.Component {
Expand Down Expand Up @@ -66,12 +66,10 @@ export default class VictoryAnimation extends React.Component {
easing: "quadInOut"
};

static contextTypes = {
getTimer: PropTypes.func
};
static contextType = TimerContext;

constructor(props) {
super(props);
constructor(props, context) {
super(props, context);
/* defaults */
this.state = {
data: Array.isArray(this.props.data) ? this.props.data[0] : this.props.data,
Expand All @@ -89,7 +87,7 @@ export default class VictoryAnimation extends React.Component {
so we bind functionToBeRunEachFrame to current instance of victory animation class
*/
this.functionToBeRunEachFrame = this.functionToBeRunEachFrame.bind(this);
this.getTimer = this.getTimer.bind(this);
this.timer = this.context.animationTimer;
}

componentDidMount() {
Expand All @@ -103,7 +101,7 @@ export default class VictoryAnimation extends React.Component {
const equalProps = isEqual(this.props, nextProps);
if (!equalProps) {
/* cancel existing loop if it exists */
this.getTimer().unsubscribe(this.loopID);
this.timer.unsubscribe(this.loopID);

/* If an object was supplied */
if (!Array.isArray(nextProps.data)) {
Expand All @@ -124,20 +122,10 @@ export default class VictoryAnimation extends React.Component {

componentWillUnmount() {
if (this.loopID) {
this.getTimer().unsubscribe(this.loopID);
this.timer.unsubscribe(this.loopID);
} else {
this.getTimer().stop();
}
}

getTimer() {
if (this.context.getTimer) {
return this.context.getTimer();
}
if (!this.timer) {
this.timer = new Timer();
this.timer.stop();
}
return this.timer;
}

toNewName(ease) {
Expand All @@ -156,13 +144,10 @@ export default class VictoryAnimation extends React.Component {
/* reset step to zero */
if (this.props.delay) {
setTimeout(() => {
this.loopID = this.getTimer().subscribe(
this.functionToBeRunEachFrame,
this.props.duration
);
this.loopID = this.timer.subscribe(this.functionToBeRunEachFrame, this.props.duration);
}, this.props.delay);
} else {
this.loopID = this.getTimer().subscribe(this.functionToBeRunEachFrame, this.props.duration);
this.loopID = this.timer.subscribe(this.functionToBeRunEachFrame, this.props.duration);
}
} else if (this.props.onEnd) {
this.props.onEnd();
Expand All @@ -186,7 +171,7 @@ export default class VictoryAnimation extends React.Component {
}
});
if (this.loopID) {
this.getTimer().unsubscribe(this.loopID);
this.timer.unsubscribe(this.loopID);
}
this.queue.shift();
this.traverseQueue();
Expand Down
67 changes: 24 additions & 43 deletions packages/victory-core/src/victory-container/victory-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import PropTypes from "prop-types";
import CustomPropTypes from "../victory-util/prop-types";
import { assign, defaults, uniqueId, isObject, isFunction } from "lodash";
import Portal from "../victory-portal/portal";
import Timer from "../victory-util/timer";
import PortalContext from "../victory-portal/portal-context";
import TimerContext from "../victory-util/timer-context";
import Helpers from "../victory-util/helpers";

export default class VictoryContainer extends React.Component {
Expand Down Expand Up @@ -37,20 +38,10 @@ export default class VictoryContainer extends React.Component {
responsive: true
};

static contextTypes = {
getTimer: PropTypes.func
};

static childContextTypes = {
portalUpdate: PropTypes.func,
portalRegister: PropTypes.func,
portalDeregister: PropTypes.func,
getTimer: PropTypes.func
};
static contextType = TimerContext;

constructor(props) {
super(props);
this.getTimer = this.getTimer.bind(this);
this.containerId =
!isObject(props) || props.containerId === undefined
? uniqueId("victory-container-")
Expand All @@ -77,40 +68,18 @@ export default class VictoryContainer extends React.Component {
}
}

getChildContext() {
return {
portalUpdate: this.portalUpdate,
portalRegister: this.portalRegister,
portalDeregister: this.portalDeregister,
getTimer: this.getTimer
};
}

componentDidMount() {
if (this.shouldHandleWheel && this.containerRef) {
this.containerRef.addEventListener("wheel", this.handleWheel);
}
}

componentWillUnmount() {
if (!this.context.getTimer) {
this.getTimer().stop();
}
if (this.shouldHandleWheel && this.containerRef) {
this.containerRef.removeEventListener("wheel", this.handleWheel);
}
}

getTimer() {
if (this.context.getTimer) {
return this.context.getTimer();
}
if (!this.timer) {
this.timer = new Timer();
}
return this.timer;
}

getIdForElement(elementName) {
return `${this.containerId}-${elementName}`;
}
Expand Down Expand Up @@ -150,16 +119,28 @@ export default class VictoryContainer extends React.Component {
style: portalSvgStyle
};
return (
<div style={defaults({}, style, divStyle)} className={className} ref={this.saveContainerRef}>
<svg {...svgProps} style={svgStyle}>
{title ? <title id={this.getIdForElement("title")}>{title}</title> : null}
{desc ? <desc id={this.getIdForElement("desc")}>{desc}</desc> : null}
{children}
</svg>
<div style={portalDivStyle}>
{React.cloneElement(portalComponent, { ...portalProps, ref: this.savePortalRef })}
<PortalContext.Provider
value={{
portalUpdate: this.portalUpdate,
portalRegister: this.portalRegister,
portalDeregister: this.portalDeregister
}}
>
<div
style={defaults({}, style, divStyle)}
className={className}
ref={this.saveContainerRef}
>
<svg {...svgProps} style={svgStyle}>
{title ? <title id={this.getIdForElement("title")}>{title}</title> : null}
{desc ? <desc id={this.getIdForElement("desc")}>{desc}</desc> : null}
{children}
</svg>
<div style={portalDivStyle}>
{React.cloneElement(portalComponent, { ...portalProps, ref: this.savePortalRef })}
</div>
</div>
</div>
</PortalContext.Provider>
);
}

Expand Down
10 changes: 10 additions & 0 deletions packages/victory-core/src/victory-portal/portal-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";

/**
* The React context object consumers may use to access the context of the
* portal.
*/
const PortalContext = React.createContext({});
PortalContext.displayName = "PortalContext";

export default PortalContext;
7 changes: 2 additions & 5 deletions packages/victory-core/src/victory-portal/victory-portal.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from "prop-types";
import { defaults } from "lodash";
import Log from "../victory-util/log";
import Helpers from "../victory-util/helpers";
import PortalContext from "./portal-context";

export default class VictoryPortal extends React.Component {
static displayName = "VictoryPortal";
Expand All @@ -18,11 +19,7 @@ export default class VictoryPortal extends React.Component {
groupComponent: <g />
};

static contextTypes = {
portalDeregister: PropTypes.func,
portalRegister: PropTypes.func,
portalUpdate: PropTypes.func
};
static contextType = PortalContext;

componentDidMount() {
if (!this.checkedContext) {
Expand Down
26 changes: 9 additions & 17 deletions packages/victory-core/src/victory-transition/victory-transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import VictoryAnimation from "../victory-animation/victory-animation";
import Collection from "../victory-util/collection";
import Helpers from "../victory-util/helpers";
import Timer from "../victory-util/timer";
import TimerContext from "../victory-util/timer-context";
import Transitions from "../victory-util/transitions";
import { defaults, isFunction, pick, isObject } from "lodash";
import isEqual from "react-fast-compare";
Expand All @@ -17,8 +17,10 @@ export default class VictoryTransition extends React.Component {
children: PropTypes.node
};

constructor(props) {
super(props);
static contextType = TimerContext;

constructor(props, context) {
super(props, context);
this.state = {
nodesShouldLoad: false,
nodesDoneLoad: false
Expand All @@ -27,7 +29,7 @@ export default class VictoryTransition extends React.Component {
const polar = child.props.polar;
this.continuous = !polar && child.type && child.type.continuous === true;
this.getTransitionState = this.getTransitionState.bind(this);
this.getTimer = this.getTimer.bind(this);
this.timer = this.context.transitionTimer;
}

componentDidMount() {
Expand All @@ -36,26 +38,16 @@ export default class VictoryTransition extends React.Component {

shouldComponentUpdate(nextProps) {
if (!isEqual(this.props, nextProps)) {
this.getTimer().bypassAnimation();
this.timer.bypassAnimation();
this.setState(this.getTransitionState(this.props, nextProps), () =>
this.getTimer().resumeAnimation()
this.timer.resumeAnimation()
);
}
return true;
}

componentWillUnmount() {
this.getTimer().stop();
}

getTimer() {
if (this.context.getTimer) {
return this.context.getTimer();
}
if (!this.timer) {
this.timer = new Timer();
}
return this.timer;
this.timer.stop();
}

getTransitionState(props, nextProps) {
Expand Down
14 changes: 14 additions & 0 deletions packages/victory-core/src/victory-util/timer-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
import Timer from "./timer";

/**
* The React context object consumers may use to access or override the global
* timer.
*/
const TimerContext = React.createContext({
transitionTimer: new Timer(),
animationTimer: new Timer()
});
TimerContext.displayName = "TimerContext";

export default TimerContext;
27 changes: 2 additions & 25 deletions packages/victory-shared-events/src/victory-shared-events.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { assign, isFunction, defaults, isEmpty, fromPairs } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import { PropTypes as CustomPropTypes, Events, Helpers, Timer } from "victory-core";
import { PropTypes as CustomPropTypes, Events, Helpers, TimerContext } from "victory-core";
import isEqual from "react-fast-compare";

export default class VictorySharedEvents extends React.Component {
Expand Down Expand Up @@ -51,29 +51,16 @@ export default class VictorySharedEvents extends React.Component {
groupComponent: <g />
};

static contextTypes = {
getTimer: PropTypes.func
};

static childContextTypes = {
getTimer: PropTypes.func
};
static contextType = TimerContext;

constructor(props) {
super(props);
this.state = this.state || {};
this.getScopedEvents = Events.getScopedEvents.bind(this);
this.getEventState = Events.getEventState.bind(this);
this.getTimer = this.getTimer.bind(this);
this.baseProps = this.getBaseProps(props);
}

getChildContext() {
return {
getTimer: this.getTimer
};
}

shouldComponentUpdate(nextProps) {
if (!isEqual(this.props, nextProps)) {
this.baseProps = this.getBaseProps(nextProps);
Expand All @@ -83,16 +70,6 @@ export default class VictorySharedEvents extends React.Component {
return true;
}

getTimer() {
if (this.context.getTimer) {
return this.context.getTimer();
}
if (!this.timer) {
this.timer = new Timer();
}
return this.timer;
}

getAllEvents(props) {
const components = ["container", "groupComponent"];
const componentEvents = Events.getComponentEvents(props, components);
Expand Down
Loading

0 comments on commit c8090c6

Please sign in to comment.