Skip to content

Commit

Permalink
fix(react-tao): implemented (un)registerReactor in Provider & signal …
Browse files Browse the repository at this point in the history
…changes

affects: @tao.js/react

React requires a call to setState to trigger render updates
implementing (un)registerReactor allows
Providers to notify Reactors
when hnadlers are triggered
  • Loading branch information
eudaimos committed Jun 3, 2018
1 parent 4e142cd commit 9ebdbe8
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 38 deletions.
40 changes: 22 additions & 18 deletions packages/react-tao/src/Provider.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import cartesian from 'cartesian';
import { AppCtx } from '@tao.js/core';

const noop = () => {};

const cleanInput = ({ term, action, orient }) => {
const incoming = { term, action, orient };
Object.keys(incoming).forEach(k => incoming[k] == null && delete incoming[k]);
return incoming;
};

const wrappedHandler = (Component, props, _provider) => (tao, data) => {
const wrappedHandler = (ComponentHandler, props, _provider) => (tao, data) => {
_provider._current = {
Component,
ComponentHandler,
tao,
props: {
...props,
...data
}
};
_provider._reactors.forEach(notify => notify());
};

class Provider {
constructor(TAO) {
this._tao = TAO;
this._current = null;
this._default = {};
this._reactors = new Map();
// this._taoIndex = new Map();
this._components = new Map();
}
Expand All @@ -44,8 +48,8 @@ class Provider {
return this;
}

addComponentHandler({ term, action, orient } = {}, Component, props) {
if (!Component) {
addComponentHandler({ term, action, orient } = {}, ComponentHandler, props) {
if (!ComponentHandler) {
throw new Error(
'cannot add a Component handler without providing a Component'
);
Expand All @@ -56,14 +60,14 @@ class Provider {
if (!permutations.length) {
return this;
}
const handler = wrappedHandler(Component, props, this);
if (!this._components.has(Component)) {
this._components.set(Component, {
const handler = wrappedHandler(ComponentHandler, props, this);
if (!this._components.has(ComponentHandler)) {
this._components.set(ComponentHandler, {
handlers: new Map(),
index: new Map()
});
}
const componentHandlers = this._components.get(Component);
const componentHandlers = this._components.get(ComponentHandler);
permutations.forEach(tao => {
const { term, action, orient } = tao;
const acKey = AppCtx.getKey(term, action, orient);
Expand All @@ -80,17 +84,17 @@ class Provider {
return this;
}

removeComponentHandler({ term, action, orient } = {}, Component) {
if (!this._components.has(Component)) {
removeComponentHandler({ term, action, orient } = {}, ComponentHandler) {
if (!this._components.has(ComponentHandler)) {
return this;
}
const componentHandlers = this._components.get(Component);
const componentHandlers = this._components.get(ComponentHandler);
if (!term && !action && !orient) {
// remove all handlers
for (let [ac, handler] of componentHandlers.handlers) {
this._tao.removeInlineHandler(ac.unwrapCtx(), handler);
}
this._components.delete(Component);
this._components.delete(ComponentHandler);
return this;
}
const ctx = Object.assign(this.defaultCtx, { term, action, orient });
Expand All @@ -113,13 +117,13 @@ class Provider {
return this;
}

// registerReactor(reactor) {
// // DO I NEED THIS?
// }
registerReactor(reactor, notify = noop) {
this._reactors.set(reactor, notify);
}

// unregisterReactor(reactor) {
// // DO I NEED THIS?
// }
unregisterReactor(reactor) {
this._reactors.delete(reactor);
}
}

export default Provider;
27 changes: 19 additions & 8 deletions packages/react-tao/src/Reactor.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { Component } from 'react';
import React, { Component, createElement } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Provider from './Provider';

const DUMMY_STATE = {};

class Reactor extends Component {
// static propTypes = {
// provider: PropTypes.instanceOf(Provider),
Expand All @@ -15,19 +17,19 @@ class Reactor extends Component {

componentWillMount() {
const { provider } = this.props;
// provider.registerReactor(this);
provider.registerReactor(this, this.onNotifyChange.bind(this));
}

componentWillUnmount() {
const { provider } = this.props;
// provider.unregisterReactor(this);
provider.unregisterReactor(this);
}

componentWillReceiveProps(nextProps) {
const { provider } = this.props;
if (provider !== nextProps.provider) {
// provider.unregisterReactor(this);
// nextProps.provider.registerReactor(this);
provider.unregisterReactor(this);
nextProps.provider.registerReactor(this, this.onNotifyChange.bind(this));
}
}

Expand Down Expand Up @@ -60,17 +62,26 @@ class Reactor extends Component {
// return false;
// }

onNotifyChange() {
this.setState(DUMMY_STATE);
}

render() {
// NOTE: Currently swallows any children
const { provider, children, ...props } = this.props;
if (!provider.current) {
return null;
}
const { Component, tao, props: childProps } = provider.current;
if (!Component) {
const { ComponentHandler, tao, props: childProps } = provider.current;
if (!ComponentHandler) {
return null;
}
return <Component {...tao} {...props} {...childProps} />;
return createElement(ComponentHandler, {
...tao,
...props,
...childProps
});
// return <ComponentHandler {...tao} {...props} {...childProps} />;
}
}

Expand Down
18 changes: 9 additions & 9 deletions packages/react-tao/test/Provider.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ describe('Provider integrates with React', () => {
// Assert
expect(uut.current).not.toBeNull();
expect(uut.current).toMatchObject({
Component,
ComponentHandler: Component,
tao: triggerAc.unwrapCtx(),
props: {
[TERM]: triggerData
Expand All @@ -167,12 +167,12 @@ describe('Provider integrates with React', () => {
const actual2 = uut.current;
expect(actual1).not.toMatchObject(actual2);
expect(actual1).toMatchObject({
Component,
ComponentHandler: Component,
tao: { t: TERM, a: ACTION, o: ORIENT },
props: { [TERM]: triggerData1 }
});
expect(actual2).toMatchObject({
Component,
ComponentHandler: Component,
tao: { t: ALT_TERM, a: ACTION, o: ORIENT },
props: { [ACTION]: triggerData2 }
});
Expand Down Expand Up @@ -206,12 +206,12 @@ describe('Provider integrates with React', () => {
expect(actual1).not.toBe(actual2);
expect(actual1).not.toMatchObject(actual2);
expect(actual1).toMatchObject({
Component,
ComponentHandler: Component,
tao: ac1.unwrapCtx(),
props: {}
});
expect(actual2).toMatchObject({
Component,
ComponentHandler: Component,
tao: ac2.unwrapCtx(),
props: {}
});
Expand Down Expand Up @@ -243,7 +243,7 @@ describe('Provider integrates with React', () => {
await TAO.setAppCtx(triggerAc);
// Assert
expect(uut.current).toMatchObject({
Component,
ComponentHandler: Component,
tao: triggerAc.unwrapCtx(),
props: {
[triggerAc.t]: triggerData
Expand All @@ -268,12 +268,12 @@ describe('Provider integrates with React', () => {
expect(actual1).not.toBe(actual2);
expect(actual1).not.toMatchObject(actual2);
expect(actual1).toMatchObject({
Component,
ComponentHandler: Component,
tao: ac1.unwrapCtx(),
props: defProps
});
expect(actual2).toMatchObject({
Component,
ComponentHandler: Component,
tao: ac2.unwrapCtx(),
props: {
...defProps,
Expand Down Expand Up @@ -352,7 +352,7 @@ describe('Provider integrates with React', () => {
expect(uut._components).toMatchObject(expected);
expect(actual).not.toBeNull();
expect(actual).toMatchObject({
Component,
ComponentHandler: Component,
tao: ac.unwrapCtx(),
props: {}
});
Expand Down
6 changes: 3 additions & 3 deletions packages/react-tao/test/Reactor.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('Reactor exports a React Component for reacting to TAO App Contexts', (
// expect(post1.type).toBe('TestComponentB');
});

xit('should render a component set as a Handler for an AC', () => {
it('should render a component set as a Handler for an AC', () => {
// Assemble
const provider = new Provider(TAO);
const triggerAc1 = new AppCtx(TERM, ACTION, ORIENT, [{ id: 1 }]);
Expand All @@ -121,8 +121,8 @@ describe('Reactor exports a React Component for reacting to TAO App Contexts', (
console.log('pre.debug:', wrapper.debug());
TAO.setAppCtx(triggerAc1);
expect(provider.current).toBeDefined();
expect(provider.current.Component).toBeDefined();
expect(provider.current.Component).toBeInstanceOf(Function);
expect(provider.current.ComponentHandler).toBeDefined();
expect(provider.current.ComponentHandler).toBeInstanceOf(Function);
console.log('post-setAppCtx.debug:', wrapper.debug());
wrapper.update();
console.log('post-update.debug:', wrapper.debug());
Expand Down

0 comments on commit 9ebdbe8

Please sign in to comment.