fix(react): handle undefined attributes better, fixes #19563, #19580 (#19588)

This commit is contained in:
Ely Lucas
2019-10-09 10:36:25 -06:00
committed by GitHub
parent 7ce916cc7c
commit 033abe994b
10 changed files with 22 additions and 37 deletions

View File

@ -1,14 +0,0 @@
import * as React from 'react';
import { deprecationWarning } from '../utils';
export class ViewManager extends React.Component<{}, {}> {
componentDidMount() {
deprecationWarning('As of @ionic/react RC2, ViewManager is no longer needed and can be removed. This component is now deprecated will be removed from @ionic/react final.');
}
render() {
return this.props.children;
}
}

View File

@ -1,3 +1,2 @@
export { IonReactRouter } from './Router';
export { ViewManager } from './ViewManager';

View File

@ -32,12 +32,12 @@ describe('syncEvent', () => {
})
});
describe('attachEventProps', () => {
describe('attachProps', () => {
it('should pass props to a dom node', () => {
const onIonClickCallback = () => {};
var div = document.createElement("div");
utils.attachEventProps(div, {
utils.attachProps(div, {
'children': [],
'style': 'color: red',
'ref': () => {},

View File

@ -4,8 +4,7 @@ import ReactDom from 'react-dom';
import { NavContext } from '../contexts/NavContext';
import { RouterDirection } from './hrefprops';
import { attachEventProps, createForwardRef, dashToPascalCase, isCoveredByReact } from './utils';
import { deprecationWarning } from './utils/dev';
import { attachProps, createForwardRef, dashToPascalCase, isCoveredByReact } from './utils';
interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
forwardedRef?: React.Ref<ElementType>;
@ -29,16 +28,11 @@ export const createReactComponent = <PropType, ElementType>(
componentDidMount() {
this.componentDidUpdate(this.props);
if (this.props.href) {
setTimeout(() => {
deprecationWarning('hrefchange', 'As of RC3, href links no longer go through the router, so transitions will not be applied to these links. To maintain transitions, use the new routerLink prop.');
}, 2000);
}
}
componentDidUpdate(prevProps: IonicReactInternalProps<PropType>) {
const node = ReactDom.findDOMNode(this) as HTMLElement;
attachEventProps(node, this.props, prevProps);
attachProps(node, this.props, prevProps);
}
private handleClick = (e: React.MouseEvent<PropType>) => {

View File

@ -1,7 +1,7 @@
import { OverlayEventDetail } from '@ionic/core';
import React from 'react';
import { attachEventProps } from './utils';
import { attachProps } from './utils';
interface OverlayBase extends HTMLElement {
present: () => Promise<void>;
@ -57,7 +57,7 @@ export const createControllerComponent = <OptionsType extends object, OverlayTyp
const overlay = this.overlay = await controller.create({
...cProps as any
});
attachEventProps(overlay, {
attachProps(overlay, {
[dismissEventName]: onDidDismiss
}, prevProps);
await overlay.present();

View File

@ -2,7 +2,7 @@ import { OverlayEventDetail } from '@ionic/core';
import React from 'react';
import ReactDOM from 'react-dom';
import { attachEventProps } from './utils';
import { attachProps } from './utils';
interface OverlayElement extends HTMLElement {
present: () => Promise<void>;
@ -68,7 +68,7 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
componentProps: {}
});
attachEventProps(overlay, elementProps, prevProps);
attachProps(overlay, elementProps, prevProps);
await overlay.present();
}

View File

@ -3,5 +3,5 @@ import { JSX } from '@ionic/core';
import { /*@__PURE__*/ createReactComponent } from './createComponent';
export const IonTabBarInner = /*@__PURE__*/createReactComponent<JSX.IonTabBar, HTMLIonTabBarElement>('ion-tab-bar');
export const IonBackButtonInner = /*@__PURE__*/createReactComponent<JSX.IonBackButton, HTMLIonBackButtonElement>('ion-back-button');
export const IonBackButtonInner = /*@__PURE__*/createReactComponent<Omit<JSX.IonBackButton, 'icon'>, HTMLIonBackButtonElement>('ion-back-button');
export const IonRouterOutletInner = /*@__PURE__*/createReactComponent<JSX.IonRouterOutlet, HTMLIonRouterOutletElement>('ion-router-outlet');

View File

@ -5,7 +5,11 @@ import { NavContext } from '../../contexts/NavContext';
import { IonicReactProps } from '../IonicReactProps';
import { IonBackButtonInner } from '../inner-proxies';
type Props = LocalJSX.IonBackButton & IonicReactProps & {
type Props = Omit<LocalJSX.IonBackButton, 'icon'> & IonicReactProps & {
icon?: {
ios: string;
md: string;
};
ref?: React.RefObject<HTMLIonBackButtonElement>;
};

View File

@ -1,6 +1,6 @@
import { camelToDashCase } from './case';
export const attachEventProps = (node: HTMLElement, newProps: any, oldProps: any = {}) => {
export const attachProps = (node: HTMLElement, newProps: any, oldProps: any = {}) => {
// add any classes in className to the class list
const className = getClassName(node.classList, newProps, oldProps);
if (className !== '') {
@ -19,10 +19,12 @@ export const attachEventProps = (node: HTMLElement, newProps: any, oldProps: any
syncEvent(node, eventNameLc, newProps[name]);
}
} else {
if (typeof newProps[name] === 'object') {
(node as any)[name] = newProps[name];
} else {
(node as any)[name] = newProps[name];
const propType = typeof newProps[name];
if (propType === 'string') {
node.setAttribute(camelToDashCase(name), newProps[name]);
} else {
(node as any)[name] = newProps[name];
}
}
});
@ -69,7 +71,7 @@ export const isCoveredByReact = (eventNameSuffix: string, doc: Document = docume
return isSupported;
};
export const syncEvent = (node: Element & {__events?: {[key: string]: ((e: Event) => any) | undefined}}, eventName: string, newEventHandler?: (e: Event) => any) => {
export const syncEvent = (node: Element & { __events?: { [key: string]: ((e: Event) => any) | undefined } }, eventName: string, newEventHandler?: (e: Event) => any) => {
const eventStore = node.__events || (node.__events = {});
const oldEventHandler = eventStore[eventName];

View File

@ -14,7 +14,7 @@ export const createForwardRef = <PropType, ElementType>(ReactComponent: any, dis
return React.forwardRef(forwardRef);
};
export * from './attachEventProps';
export * from './attachProps';
export * from './case';
export const isPlatform = (platform: Platforms) => {