diff --git a/base/__tests__/inferno/callbag/index.tsx b/base/__tests__/inferno/callbag/index.tsx index 83c636ab..e421519f 100644 --- a/base/__tests__/inferno/callbag/index.tsx +++ b/base/__tests__/inferno/callbag/index.tsx @@ -2,9 +2,16 @@ import { createElement } from 'inferno-create-element' import { withEffects, Handler, - ObservableComponent + ObservableComponent, + PropEffect } from '../../../../packages/refract-inferno-callbag/src' -import aperture, { Effect, Props } from '../../react/callbag/aperture' +import { + aperture, + toPropsAperture, + asPropsAperture, + Effect, + Props +} from '../../react/callbag/aperture' import { mount } from 'enzyme' describe('refract-inferno-callbag', () => { @@ -80,4 +87,53 @@ describe('refract-inferno-callbag', () => { type: 'Stop' }) }) + + it('should map props to wrapped component', () => { + interface Props { + prop: string + } + interface ChildProps { + newProp: string + } + const BaseComponent = jest.fn().mockReturnValue(
) + const hander = () => () => void 0 + const WithEffects = withEffects( handler: Handler
, errorHandler?: ErrorHandler
) => (aperture: Aperture
, instance: any) => { + instance.state = { + children: null + } + + const setState = state => { + if (instance.unmounted) { + return + } + if (instance.mounted) { + instance.setState(state) + } else { + instance.state = state + } + } + + const finalHandler = initialProps => { + const effectHandler = handler(initialProps) + + return effect => { + if (effect && effect.type === PROPS_EFFECT) { + setState(effect.payload) + } else { + effectHandler(effect) + } + } + } + const listeners: Listeners = { mount: [], unmount: [], @@ -111,7 +139,7 @@ const configureComponent =
(
const sinkSubscription: Subscription = subscribeToSink (
}
instance.getChildProps = () => {
- const { children, ...props } = instance.props
+ const { props = {}, replace } = instance.state
+
+ if (replace === true) {
+ return Object.assign({}, props, {
+ pushEvent
+ })
+ } else if (replace === false) {
+ return Object.assign({}, instance.props, decoratedProps, props, {
+ pushEvent
+ })
+ }
- return Object.assign({}, props, decoratedProps, {
+ return Object.assign({}, instance.props, decoratedProps, {
pushEvent
})
}
diff --git a/base/react/effects.ts b/base/react/effects.ts
new file mode 100644
index 00000000..5e9e1038
--- /dev/null
+++ b/base/react/effects.ts
@@ -0,0 +1,25 @@
+export const PROPS_EFFECT: string = '@@refract/effect/props'
+
+export interface PropEffect {
+ type: string
+ payload: {
+ replace: boolean
+ props: P
+ }
+}
+
+export const toProps = (props: P): PropEffect => ({
+ type: PROPS_EFFECT,
+ payload: {
+ replace: false,
+ props
+ }
+})
+
+export const asProps = (props: P): PropEffect => ({
+ type: PROPS_EFFECT,
+ payload: {
+ replace: true,
+ props
+ }
+})
diff --git a/base/react/index.ts b/base/react/index.ts
index 7c350f23..dd47a491 100644
--- a/base/react/index.ts
+++ b/base/react/index.ts
@@ -2,6 +2,7 @@ import { withEffects } from './withEffects'
import { ObservableComponent, Aperture } from './observable'
import { ErrorHandler, Handler } from './baseTypes'
import { compose, Compose } from './compose'
+import { asProps, toProps, PROPS_EFFECT, PropEffect } from './effects'
export {
withEffects,
@@ -10,5 +11,9 @@ export {
Handler,
ErrorHandler,
compose,
- Compose
+ Compose,
+ asProps,
+ toProps,
+ PropEffect,
+ PROPS_EFFECT
}
diff --git a/base/react/observable_callbag.ts b/base/react/observable_callbag.ts
index ed3acd65..6c93ce8e 100644
--- a/base/react/observable_callbag.ts
+++ b/base/react/observable_callbag.ts
@@ -14,7 +14,7 @@ export interface Subscription {
}
export interface ObservableComponent {
- observe: (
+export const withEffects = (
handler: Handler ,
errorHandler?: ErrorHandler
) => (aperture: Aperture ) => (
- BaseComponent: React.ComponentType
+ BaseComponent: React.ComponentType =>
class WithEffects extends React.PureComponent {
private triggerMount: () => void
private triggerUnmount: () => void
private reDecorateProps: (nextProps: P) => void
private pushProps: (props: P) => void
- private getChildProps: () => P & { pushEvent: PushEvent }
+ private getChildProps: () => CP & { pushEvent: PushEvent }
+ private mounted: boolean = false
+ private unmounted: boolean = false
constructor(props: any, context: any) {
super(props, context)
@@ -25,6 +27,7 @@ export const withEffects = (
}
public componentDidMount() {
+ this.mounted = true
this.triggerMount()
}
@@ -37,14 +40,11 @@ export const withEffects = (
}
public componentWillUnmount() {
+ this.unmounted = true
this.triggerUnmount()
}
public render() {
- return React.createElement(
- BaseComponent,
- this.getChildProps(),
- this.props.children
- )
+ return React.createElement(BaseComponent, this.getChildProps())
}
}
diff --git a/base/react/withEffects_inferno.ts b/base/react/withEffects_inferno.ts
index 890eccce..5e96ad51 100644
--- a/base/react/withEffects_inferno.ts
+++ b/base/react/withEffects_inferno.ts
@@ -6,18 +6,20 @@ import configureComponent from './configureComponent'
import { Handler, ErrorHandler, PushEvent } from './baseTypes'
import { Aperture } from './observable'
-export const withEffects = (
+export const withEffects = (
handler: Handler ,
errorHandler?: ErrorHandler
) => (aperture: Aperture ) => (
- BaseComponent: ComponentType
+ BaseComponent: ComponentType =>
class WithEffects extends Component {
private triggerMount: () => void
private triggerUnmount: () => void
private reDecorateProps: (nextProps: P) => void
private pushProps: (props: P) => void
- private getChildProps: () => P & { pushEvent: PushEvent }
+ private getChildProps: () => CP & { pushEvent: PushEvent }
+ private mounted: boolean = false
+ private unmounted: boolean = false
constructor(props: any, context: any) {
super(props, context)
@@ -26,6 +28,7 @@ export const withEffects = (
}
public componentDidMount() {
+ this.mounted = true
this.triggerMount()
}
@@ -38,14 +41,11 @@ export const withEffects = (
}
public componentWillUnmount() {
+ this.unmounted = true
this.triggerUnmount()
}
public render() {
- return createElement(
- BaseComponent,
- this.getChildProps(),
- this.props.children
- )
+ return createElement(BaseComponent, this.getChildProps())
}
}
diff --git a/base/react/withEffects_preact.ts b/base/react/withEffects_preact.ts
index db0b6c1b..52659dd7 100644
--- a/base/react/withEffects_preact.ts
+++ b/base/react/withEffects_preact.ts
@@ -5,18 +5,20 @@ import configureComponent from './configureComponent'
import { Handler, ErrorHandler, PushEvent } from './baseTypes'
import { Aperture } from './observable'
-export const withEffects = (
+export const withEffects = (
handler: Handler ,
errorHandler?: ErrorHandler
) => (aperture: Aperture ) => (
- BaseComponent: ComponentFactory
+ BaseComponent: ComponentFactory =>
class WithEffects extends Component {
private triggerMount: () => void
private triggerUnmount: () => void
private reDecorateProps: (nextProps: P) => void
private pushProps: (props: P) => void
- private getChildProps: () => P & { pushEvent: PushEvent }
+ private getChildProps: () => CP & { pushEvent: PushEvent }
+ private mounted: boolean = false
+ private unmounted: boolean = false
constructor(props: P) {
super(props)
@@ -25,6 +27,7 @@ export const withEffects = (
}
public componentDidMount() {
+ this.mounted = true
this.triggerMount()
}
@@ -37,10 +40,11 @@ export const withEffects = (
}
public componentWillUnmount() {
+ this.unmounted = true
this.triggerUnmount()
}
public render() {
- return h(BaseComponent, this.getChildProps(), this.props.children)
+ return h(BaseComponent, this.getChildProps())
}
}
diff --git a/scripts/copy.js b/scripts/copy.js
index e3454bcc..c00ce3b0 100644
--- a/scripts/copy.js
+++ b/scripts/copy.js
@@ -11,6 +11,7 @@ const getPackages = require('../packages')
const filesPerBaseDir = {
react: [
'baseTypes.ts',
+ 'effects.ts',
'index.ts',
({ mainLib }) => ({
src: `withEffects${mainLib === 'react' ? '' : `_${mainLib}`}.ts`,