Skip to content

Commit

Permalink
feat(*): Add debugLog mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
christopherthielen committed Nov 14, 2018
1 parent 63bb051 commit 94fe097
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 44 deletions.
4 changes: 2 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ui-router-react-hybrid",
"description": "https://stackblitz.com/edit/ui-router-react-hybrid",
"dependencies": {
"@uirouter/react-hybrid": "latest",
"@uirouter/react-hybrid": "file:.yalc/@uirouter/react-hybrid",
"@uirouter/visualizer": "6.0.0",
"angular": "1.7.0",
"prop-types": "15.6.1",
Expand All @@ -22,4 +22,4 @@
"devDependencies": {
"@uirouter/cypress-runner": "^1.0.7"
}
}
}
33 changes: 17 additions & 16 deletions src/angularjs/ReactUIViewAdapterComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { hybridModule } from './module';
import { filter } from '@uirouter/core';
import ReactUIView from '../react/ReactUIView';
import { hybridModule } from './module';
import { debug as debugLog } from '../debug';

// When an angularjs `ui-view` is instantiated, also create an react-ui-view-adapter (which creates a react UIView)
hybridModule.directive('uiView', function() {
Expand All @@ -11,7 +12,7 @@ hybridModule.directive('uiView', function() {
compile: function(tElem, tAttrs) {
let { name, uiView } = tAttrs;
name = name || uiView || '$default';
// console.log('Creating react-ui-view-adapter', tElem);
debugLog('angularjs ui-view', '', '.compile()', 'Creating react-ui-view-adapter', tElem);
tElem.html(`<react-ui-view-adapter name="${name}"></react-ui-view-adapter>`);
},
};
Expand All @@ -26,20 +27,17 @@ hybridModule.directive('reactUiViewAdapter', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
const debug = (method: string, message: string, ...args) =>
debugLog('angularjs react-ui-view-adapter', `${$id}/${attrs.name}`, method, message, ...args);

const el = elem[0];
let _ref = null;
let destroyed = false;
const $id = id++;
const ignoredAttrKeys = ['$$element', '$attr'];
attrs = filter(attrs, (val, key) => ignoredAttrKeys.indexOf(key) === -1) as any;

// console.log(`${$id}: linking react-ui-view-adapter into `, el, attrs)

const log = (msg, UIViewRef) => {
const id = UIViewRef && UIViewRef.state && UIViewRef.state.id;
const cmp = UIViewRef && UIViewRef.componentInstance;
console.log(msg, `Has UIViewRef: ${!!UIViewRef}`, id, cmp);
};
debug('.link()', 'linking react-ui-view-adapter into ', el, attrs);

// The UIView ref callback, which is called after the initial render
const ref = ref => {
Expand All @@ -56,7 +54,7 @@ hybridModule.directive('reactUiViewAdapter', function() {

_ref = ref;

// log(`${$id}: received new React UIView ref:`, ref);
debug('.ref()', 'Received new React UIView ref', ref);

// Add the $uiView data to the adapter element to provide context to child angular elements
provideContextToAngularJSChildren();
Expand All @@ -65,7 +63,8 @@ hybridModule.directive('reactUiViewAdapter', function() {

// The render callback for the React UIView
const render = (cmp, props: object) => {
// log('render', _ref);
debug('.render()', `has ref: ${!!_ref}`);

provideContextToAngularJSChildren();
// Only create the children when the _ref is ready
return !_ref ? null : React.createElement(cmp, props);
Expand All @@ -74,7 +73,9 @@ hybridModule.directive('reactUiViewAdapter', function() {
const provideContextToAngularJSChildren = () => {
const $cfg = _ref && _ref.uiViewData && _ref.uiViewData.config;
const $uiView = _ref && _ref.uiViewAddress;
// console.log(`${$id}: providing context to angularjs children`, el, $cfg, $uiView);

debug('.provideContextToAngularJSChildren', '', el, $cfg, $uiView);

if (!$cfg || !$uiView) {
elem.removeData('$uiView');
} else {
Expand All @@ -83,20 +84,20 @@ hybridModule.directive('reactUiViewAdapter', function() {
};

function renderReactUIView() {
// console.log(`${$id}: rendering react uiview into container`, el);
if (destroyed) {
// console.error(`${$id}: react-ui-view-adapter has already been destroyed -- not rendering React UIView`);
debug('.renderReactUIView()', `already destroyed -- will not render React UIView`);
return;
}

const props = { ...attrs, render, wrap: false, refFn: ref };
const setChildViewProps = (scope as any).setChildViewProps;
if (setChildViewProps) {
debug('.renderReactUIView()', `will setChildViewProps({ name: '${props['name']}' })`, el);
setChildViewProps(props, el);
} else {
debug('.renderReactUIView()', `ReactDOM.render(<ReactUIView name="${props['name']}"/>)`, el);
ReactDOM.render<any>(<ReactUIView {...props} />, el as any);
}
// console.log(`${$id}: rendering ReactUIView with props`, props);
}

scope.$on('$destroy', () => {
Expand All @@ -106,7 +107,7 @@ hybridModule.directive('reactUiViewAdapter', function() {
setChildViewProps(null);
} else {
const unmounted = ReactDOM.unmountComponentAtNode(el);
// console.log(`${$id}: angular $destroy event -- unmountComponentAtNode(): ${unmounted}`, el);
debug('.$on("$destroy")', `unmountComponentAtNode(): ${unmounted}`, el);
}
// Remove using jQLite element for cross-browser compatibility.
elem.remove();
Expand Down
4 changes: 4 additions & 0 deletions src/debug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const debug = (component: string, id: string, method: string, message: string, ...args) => {
if (window && window['debugReactHybrid'] !== true) return;
console.log(`${component}[${id}]${method}: ${message}`, ...args);
};
33 changes: 19 additions & 14 deletions src/react/ReactUIView.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { UIRouterConsumer, UIView, UIViewConsumer } from "@uirouter/react";
import { UIRouterContextComponent } from "./UIRouterReactContext";
import * as React from "react";
import * as React from 'react';
import { UIRouterConsumer, UIView, UIViewConsumer } from '@uirouter/react';
import { UIRouterContextComponent } from './UIRouterReactContext';
import { debug as debugLog } from '../debug';

const InternalUIView = UIView.__internalViewComponent;

const ReactUIView = ({ refFn, ...props }) => (
<UIRouterContextComponent parentContextLevel="3" inherited={false}>
<UIRouterConsumer>
{router => (
<UIViewConsumer>
{parentUiView => <InternalUIView {...props} ref={refFn} parentUIView={parentUiView} router={router} />}
</UIViewConsumer>
)}
</UIRouterConsumer>
</UIRouterContextComponent>
);
const ReactUIView = ({ refFn, ...props }) => {
debugLog('react ReactUIView', `?/${props['name']}`, '.render()', '');

return (
<UIRouterContextComponent parentContextLevel="3" inherited={false}>
<UIRouterConsumer>
{router => (
<UIViewConsumer>
{parentUiView => <InternalUIView {...props} ref={refFn} parentUIView={parentUiView} router={router} />}
</UIViewConsumer>
)}
</UIRouterConsumer>
</UIRouterContextComponent>
);
};

export default ReactUIView;
41 changes: 29 additions & 12 deletions src/react/UIViewMonkeyPatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { UIView } from '@uirouter/react';
import { AngularUIView } from './AngularUIView';
import ReactUIView from "./ReactUIView";
import ReactUIView from './ReactUIView';
import { debug as debugLog } from '../debug';

/**
* Monkey patches the @uirouter/react UIView such that:
Expand All @@ -22,44 +23,60 @@ import ReactUIView from "./ReactUIView";
*/
const realRender = UIView.prototype.render;

let id = 0;

class PortalView extends React.PureComponent {
state = {
private $id = id++;

public state = {
props: null,
target: null,
};

private debug = (method: string, message: string, ...args) =>
debugLog('react PortalView', `${this.$id}/${this.props['name']}`, method, message, ...args);

public componentWillUnmount() {
this.debug('.componentWillUnmount()', '');
}

setChildViewProps = (props, target) => {
this.debug('.setChildViewProps()', JSON.stringify(props), target);
this.setState({ props, target });
};

renderPortal() {
if (!this.state) return null;
const { props, target } = this.state;

if (props && target) {
return ReactDOM.createPortal(
<ReactUIView {...props} />,
target
this.debug(
`.renderPortal({ name: ${this.props['name']} })`,
'rendering portal',
this.state.props,
this.state.target
);
return ReactDOM.createPortal(<ReactUIView {...props} />, target);
}

this.debug(`.renderPortal({ name: ${this.props['name']} })`, 'no target; not rendering portal');
return null;
}

render() {
return (
<React.Fragment>
<AngularUIView {...this.props} setChildViewProps={this.setChildViewProps}/>
<AngularUIView {...this.props} setChildViewProps={this.setChildViewProps} />
{this.renderPortal()}
</React.Fragment>
)
);
}
}

UIView.prototype.render = function() {
if (this.props.wrap === false) {
return realRender.apply(this, arguments);
debugLog('react UIView', `${this.$id}/${this.props['name']}`, '.render()', 'realRender.apply(this, arguments)');
return <div className="UIView">{realRender.apply(this, arguments)}</div>;
}

return (
<PortalView {...this.props}/>
);
return <PortalView {...this.props} />;
};

0 comments on commit 94fe097

Please sign in to comment.