зеркало из https://github.com/microsoft/reactxp.git
Update usages of findDOMNode to indicate that it returns null (#761)
Fix a bug in web animations that results in a crash due to this
This commit is contained in:
Родитель
7347886ab9
Коммит
18d4a2e5b1
|
@ -343,11 +343,13 @@ export class NavigatorImpl extends NavigatorBase<NavigatorState> {
|
|||
}
|
||||
|
||||
private _updateDimensionsCache() {
|
||||
const transitioner = ReactDOM.findDOMNode(this.refs['transitioner']) as HTMLElement;
|
||||
this._dimensions = {
|
||||
width: transitioner.offsetWidth,
|
||||
height: transitioner.offsetHeight
|
||||
};
|
||||
const transitioner = ReactDOM.findDOMNode(this.refs['transitioner']) as HTMLElement|null;
|
||||
if (transitioner) {
|
||||
this._dimensions = {
|
||||
width: transitioner.offsetWidth,
|
||||
height: transitioner.offsetHeight
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to extract Navigator's Scene config from the route
|
||||
|
@ -631,11 +633,13 @@ export class NavigatorImpl extends NavigatorBase<NavigatorState> {
|
|||
// setNativeProps.
|
||||
private _setNativeStyles(component: React.ReactInstance, currentStyles: any) {
|
||||
// Grab the actual element from the DOM.
|
||||
let element = ReactDOM.findDOMNode(component) as HTMLElement;
|
||||
const flatStyles: RX.Types.ViewStyleRuleSet = _.isArray(currentStyles) ? _.flatten(currentStyles) : currentStyles;
|
||||
let element = ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
if (element) {
|
||||
const flatStyles: RX.Types.ViewStyleRuleSet = _.isArray(currentStyles) ? _.flatten(currentStyles) : currentStyles;
|
||||
|
||||
// Modify styles
|
||||
_.assign(element.style, flatStyles);
|
||||
// Modify styles
|
||||
_.assign(element.style, flatStyles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,16 +17,18 @@ import Types = require('../common/Types');
|
|||
class Video extends RX.Component<Types.VideoProps, {}> {
|
||||
componentDidMount() {
|
||||
// We need to manually install the onEnded handler because. React doesn't support this.
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
videoDOM.onended = () => {
|
||||
if (this.props.onEnded) {
|
||||
this.props.onEnded();
|
||||
}
|
||||
};
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.onended = () => {
|
||||
if (this.props.onEnded) {
|
||||
this.props.onEnded();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
// Prevent Chrome based browsers to leak video elements
|
||||
videoDOM.src = '';
|
||||
|
@ -85,35 +87,35 @@ class Video extends RX.Component<Types.VideoProps, {}> {
|
|||
}
|
||||
|
||||
seek(position: number) {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.currentTime = position;
|
||||
}
|
||||
}
|
||||
|
||||
seekPercent(percentage: number) {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.currentTime = percentage * videoDOM.duration;
|
||||
}
|
||||
}
|
||||
|
||||
play() {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.play();
|
||||
}
|
||||
}
|
||||
|
||||
pause() {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.pause();
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.pause();
|
||||
videoDOM.currentTime = 0;
|
||||
|
@ -121,7 +123,7 @@ class Video extends RX.Component<Types.VideoProps, {}> {
|
|||
}
|
||||
|
||||
mute(muted: boolean) {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
videoDOM.muted = muted;
|
||||
}
|
||||
|
@ -129,7 +131,7 @@ class Video extends RX.Component<Types.VideoProps, {}> {
|
|||
|
||||
private _onLoadedData = () => {
|
||||
if (this.props.onLoadedData) {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
|
||||
if (videoDOM) {
|
||||
const loadInfo: Types.VideoInfo = {
|
||||
|
@ -146,7 +148,7 @@ class Video extends RX.Component<Types.VideoProps, {}> {
|
|||
|
||||
private _onTimeUpdate = () => {
|
||||
if (this.props.onProgress) {
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement;
|
||||
let videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement|null;
|
||||
if (videoDOM) {
|
||||
this.props.onProgress({
|
||||
currentTime: videoDOM.currentTime,
|
||||
|
|
|
@ -395,14 +395,20 @@ function createAnimatedComponent<PropsType extends Types.CommonProps>(Component:
|
|||
|
||||
let attrib = this._findAnimatedAttributeByValue(this._animatedAttributes, valueObject);
|
||||
if (attrib) {
|
||||
let cssValue = this._generateCssAttributeValue(attrib, valueObject, valueObject._getValue());
|
||||
(this._getDomNode().style as any)[attrib] = cssValue;
|
||||
const domNode = this._getDomNode();
|
||||
if (domNode) {
|
||||
const cssValue = this._generateCssAttributeValue(attrib, valueObject, valueObject._getValue());
|
||||
(domNode.style as any)[attrib] = cssValue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let transform = this._findAnimatedAttributeByValue(this._animatedTransforms, valueObject);
|
||||
if (transform) {
|
||||
this._getDomNode().style.transform = this._generateCssTransformList(true);
|
||||
const domNode = this._getDomNode();
|
||||
if (domNode) {
|
||||
domNode.style.transform = this._generateCssTransformList(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,9 +491,12 @@ function createAnimatedComponent<PropsType extends Types.CommonProps>(Component:
|
|||
// mapping the interpolated value in reverse. Instead, we'll
|
||||
// simply update it to the "toValue".
|
||||
if (!valueObject._isInterpolated()) {
|
||||
let computedStyle = window.getComputedStyle(this._getDomNode(), undefined);
|
||||
if (computedStyle && (computedStyle as any)[attrib]) {
|
||||
partialValue = (computedStyle as any)[attrib];
|
||||
const domNode = this._getDomNode();
|
||||
if (domNode) {
|
||||
let computedStyle = window.getComputedStyle(domNode, undefined);
|
||||
if (computedStyle && (computedStyle as any)[attrib]) {
|
||||
partialValue = (computedStyle as any)[attrib];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,8 +533,8 @@ function createAnimatedComponent<PropsType extends Types.CommonProps>(Component:
|
|||
return partialValue;
|
||||
}
|
||||
|
||||
private _getDomNode(): HTMLElement {
|
||||
return ReactDOM.findDOMNode(this._mountedComponent) as HTMLElement;
|
||||
private _getDomNode(): HTMLElement|null {
|
||||
return ReactDOM.findDOMNode(this._mountedComponent) as HTMLElement|null;
|
||||
}
|
||||
|
||||
// Looks for the specified value object in the specified map. Returns
|
||||
|
@ -571,30 +580,33 @@ function createAnimatedComponent<PropsType extends Types.CommonProps>(Component:
|
|||
}
|
||||
|
||||
if (activeTransitions.length > 0) {
|
||||
executeTransition(this._getDomNode(), activeTransitions, () => {
|
||||
// Clear all of the active transitions and invoke the onEnd callbacks.
|
||||
let completeTransitions: ExtendedTransition[] = [];
|
||||
const domNode = this._getDomNode();
|
||||
if (domNode) {
|
||||
executeTransition(domNode, activeTransitions, () => {
|
||||
// Clear all of the active transitions and invoke the onEnd callbacks.
|
||||
let completeTransitions: ExtendedTransition[] = [];
|
||||
|
||||
_.each(this._animatedAttributes, attrib => {
|
||||
if (attrib.activeTransition) {
|
||||
completeTransitions.push(attrib.activeTransition);
|
||||
delete attrib.activeTransition;
|
||||
}
|
||||
});
|
||||
_.each(this._animatedAttributes, attrib => {
|
||||
if (attrib.activeTransition) {
|
||||
completeTransitions.push(attrib.activeTransition);
|
||||
delete attrib.activeTransition;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(this._animatedTransforms, transform => {
|
||||
if (transform.activeTransition) {
|
||||
completeTransitions.push(transform.activeTransition);
|
||||
delete transform.activeTransition;
|
||||
}
|
||||
});
|
||||
_.each(this._animatedTransforms, transform => {
|
||||
if (transform.activeTransition) {
|
||||
completeTransitions.push(transform.activeTransition);
|
||||
delete transform.activeTransition;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(completeTransitions, transition => {
|
||||
if (transition.onEnd) {
|
||||
transition.onEnd({ finished: true });
|
||||
}
|
||||
_.each(completeTransitions, transition => {
|
||||
if (transition.onEnd) {
|
||||
transition.onEnd({ finished: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ export class Button extends ButtonBase {
|
|||
|
||||
focus() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLButtonElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLButtonElement|null;
|
||||
if (el) {
|
||||
el.focus();
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ export class Button extends ButtonBase {
|
|||
|
||||
blur() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLButtonElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLButtonElement|null;
|
||||
if (el) {
|
||||
el.blur();
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ export class Link extends React.Component<Types.LinkProps, Types.Stateless> {
|
|||
|
||||
focus() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLAnchorElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLAnchorElement|null;
|
||||
if (el) {
|
||||
el.focus();
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ export class Link extends React.Component<Types.LinkProps, Types.Stateless> {
|
|||
|
||||
blur() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLAnchorElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLAnchorElement|null;
|
||||
if (el) {
|
||||
el.blur();
|
||||
}
|
||||
|
|
|
@ -306,7 +306,8 @@ export class RootView extends React.Component<RootViewProps, RootViewState> {
|
|||
}
|
||||
|
||||
protected _onMount = (component: PopupContainerView|null) => {
|
||||
this._mountedComponent = component ? ReactDOM.findDOMNode(component) as HTMLElement : undefined;
|
||||
const domNode = component && ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
this._mountedComponent = domNode ? domNode : undefined;
|
||||
}
|
||||
|
||||
private _tryClosePopup = (e: MouseEvent) => {
|
||||
|
@ -370,8 +371,8 @@ export class RootView extends React.Component<RootViewProps, RootViewState> {
|
|||
}
|
||||
|
||||
private _determineIfClickOnElement(elementReference: React.Component<any, any>, eventSource: Element|null|undefined): boolean {
|
||||
const element = ReactDOM.findDOMNode(elementReference) as HTMLElement;
|
||||
const isClickOnElement = element && !!eventSource && element.contains(eventSource);
|
||||
const element = ReactDOM.findDOMNode(elementReference) as HTMLElement|null;
|
||||
const isClickOnElement = !!element && !!eventSource && element.contains(eventSource);
|
||||
return isClickOnElement;
|
||||
}
|
||||
|
||||
|
@ -591,7 +592,7 @@ export class RootView extends React.Component<RootViewProps, RootViewState> {
|
|||
return;
|
||||
}
|
||||
|
||||
let anchor = ReactDOM.findDOMNode(anchorComponent) as HTMLElement;
|
||||
let anchor = ReactDOM.findDOMNode(anchorComponent) as HTMLElement|null;
|
||||
|
||||
// If the anchor has disappeared, dismiss the popup.
|
||||
if (!anchor) {
|
||||
|
|
|
@ -226,7 +226,7 @@ export class ScrollView extends ViewBase<Types.ScrollViewProps, Types.Stateless>
|
|||
this._customScrollbar = undefined;
|
||||
}
|
||||
|
||||
let element = ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
let element = ReactDOM.findDOMNode(this) as HTMLElement|null;
|
||||
if (element) {
|
||||
this._customScrollbar = new CustomScrollbar(element);
|
||||
const horizontalHidden = (props.horizontal && props.showsHorizontalScrollIndicator === false);
|
||||
|
|
|
@ -153,7 +153,7 @@ export class Text extends TextBase {
|
|||
|
||||
blur() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement|null;
|
||||
if (el) {
|
||||
el.blur();
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ export class Text extends TextBase {
|
|||
|
||||
focus() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement|null;
|
||||
if (el) {
|
||||
el.focus();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export class UserInterface extends RX.UserInterface {
|
|||
|
||||
let deferred = SyncTasks.Defer<Types.LayoutInfo>();
|
||||
|
||||
const componentDomNode = ReactDOM.findDOMNode(component) as HTMLElement;
|
||||
const componentDomNode = ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
|
||||
if (!componentDomNode) {
|
||||
deferred.reject('measureLayoutRelativeToWindow failed');
|
||||
|
@ -53,8 +53,8 @@ export class UserInterface extends RX.UserInterface {
|
|||
|
||||
let deferred = SyncTasks.Defer<Types.LayoutInfo>();
|
||||
|
||||
const componentDomNode = ReactDOM.findDOMNode(component) as HTMLElement;
|
||||
const ancestorDomNode = ReactDOM.findDOMNode(ancestor) as HTMLElement;
|
||||
const componentDomNode = ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
const ancestorDomNode = ReactDOM.findDOMNode(ancestor) as HTMLElement|null;
|
||||
|
||||
if (!componentDomNode || !ancestorDomNode) {
|
||||
deferred.reject('measureLayoutRelativeToAncestor failed');
|
||||
|
|
|
@ -157,7 +157,7 @@ export class View extends ViewBase<Types.ViewProps, Types.Stateless> {
|
|||
|
||||
let initResizer = (key: 'grow' | 'shrink', ref: any) => {
|
||||
const cur: HTMLElement|undefined = this._resizeDetectorNodes[key];
|
||||
const element = ReactDOM.findDOMNode(ref) as HTMLElement;
|
||||
const element = ReactDOM.findDOMNode(ref) as HTMLElement|null;
|
||||
|
||||
if (cur) {
|
||||
delete this._resizeDetectorNodes[key];
|
||||
|
@ -257,7 +257,7 @@ export class View extends ViewBase<Types.ViewProps, Types.Stateless> {
|
|||
if (!this._isMounted) {
|
||||
return null;
|
||||
}
|
||||
return ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
return ReactDOM.findDOMNode(this) as HTMLElement|null;
|
||||
}
|
||||
|
||||
private _isHidden(): boolean {
|
||||
|
@ -463,7 +463,7 @@ export class View extends ViewBase<Types.ViewProps, Types.Stateless> {
|
|||
|
||||
blur() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement|null;
|
||||
if (el) {
|
||||
el.blur();
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ export class View extends ViewBase<Types.ViewProps, Types.Stateless> {
|
|||
|
||||
focus() {
|
||||
if (this._isMounted) {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLDivElement|null;
|
||||
if (el) {
|
||||
el.focus();
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export class AnimateListEdits extends React.Component<AnimateListEditsProps, Typ
|
|||
let delay = 0;
|
||||
if (edits.removed.length > 0 && this.props.animateChildLeave) {
|
||||
edits.removed.forEach(function (move) {
|
||||
let domNode = ReactDOM.findDOMNode(move.element) as HTMLElement;
|
||||
let domNode = ReactDOM.findDOMNode(move.element) as HTMLElement|null;
|
||||
if (domNode) {
|
||||
domNode.style.transform = 'translateY(' + -move.topDelta + 'px)';
|
||||
|
||||
|
@ -56,7 +56,7 @@ export class AnimateListEdits extends React.Component<AnimateListEditsProps, Typ
|
|||
if (edits.moved.length > 0 && this.props.animateChildMove) {
|
||||
edits.moved.forEach(function (move) {
|
||||
counter++;
|
||||
let domNode = ReactDOM.findDOMNode(move.element) as HTMLElement;
|
||||
let domNode = ReactDOM.findDOMNode(move.element) as HTMLElement|null;
|
||||
if (domNode) {
|
||||
executeTransition(domNode, [{
|
||||
property: 'transform',
|
||||
|
@ -74,14 +74,17 @@ export class AnimateListEdits extends React.Component<AnimateListEditsProps, Typ
|
|||
if (edits.added.length > 0 && this.props.animateChildEnter) {
|
||||
edits.added.forEach(function (move) {
|
||||
counter++;
|
||||
executeTransition(ReactDOM.findDOMNode(move.element) as HTMLElement, [{
|
||||
property: 'opacity',
|
||||
from: 0,
|
||||
to: 1,
|
||||
delay: delay,
|
||||
duration: 150,
|
||||
timing: 'linear'
|
||||
}], animationCompleted);
|
||||
let domNode = ReactDOM.findDOMNode(move.element) as HTMLElement|null;
|
||||
if (domNode) {
|
||||
executeTransition(domNode, [{
|
||||
property: 'opacity',
|
||||
from: 0,
|
||||
to: 1,
|
||||
delay: delay,
|
||||
duration: 150,
|
||||
timing: 'linear'
|
||||
}], animationCompleted);
|
||||
}
|
||||
});
|
||||
}
|
||||
animationCompleted();
|
||||
|
|
|
@ -92,21 +92,21 @@ export class FocusManager extends FocusManagerBase {
|
|||
}
|
||||
|
||||
protected /* static */ addFocusListenerOnComponent(component: FocusableComponentInternal, onFocus: () => void): void {
|
||||
const el = ReactDOM.findDOMNode(component) as HTMLElement;
|
||||
const el = ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
if (el) {
|
||||
el.addEventListener('focus', onFocus);
|
||||
}
|
||||
}
|
||||
|
||||
protected /* static */ removeFocusListenerFromComponent(component: FocusableComponentInternal, onFocus: () => void): void {
|
||||
const el = ReactDOM.findDOMNode(component) as HTMLElement;
|
||||
const el = ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
if (el) {
|
||||
el.removeEventListener('focus', onFocus);
|
||||
}
|
||||
}
|
||||
|
||||
protected /* static */ focusComponent(component: FocusableComponentInternal): boolean {
|
||||
const el = ReactDOM.findDOMNode(component) as HTMLElement;
|
||||
const el = ReactDOM.findDOMNode(component) as HTMLElement|null;
|
||||
if (el && el.focus) {
|
||||
FocusManager.setLastFocusedProgrammatically(el);
|
||||
el.focus();
|
||||
|
@ -243,7 +243,7 @@ export class FocusManager extends FocusManagerBase {
|
|||
const restrictionRemoved = newTabIndex === undefined;
|
||||
|
||||
if ((storedComponent.curTabIndex !== newTabIndex) || (storedComponent.curAriaHidden !== newAriaHidden)) {
|
||||
const el = ReactDOM.findDOMNode(storedComponent.component) as HTMLElement;
|
||||
const el = ReactDOM.findDOMNode(storedComponent.component) as HTMLElement|null;
|
||||
|
||||
if (el) {
|
||||
if (storedComponent.curTabIndex !== newTabIndex) {
|
||||
|
@ -365,7 +365,7 @@ export function applyFocusableComponentMixin(Component: any, isConditionallyFocu
|
|||
|
||||
if (origFocus) {
|
||||
Component.prototype.focus = function () {
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLElement;
|
||||
const el = ReactDOM.findDOMNode(this) as HTMLElement|null;
|
||||
if (el) {
|
||||
FocusManager.setLastFocusedProgrammatically(el);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче