diff --git a/package.json b/package.json index 392a7b4..64a3076 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ }, "scripts": { "setup": "typings install", - "start": "http-server", + "start": "http-server -c-1", "build": "npm run setup && npm run test && webpack", "watch": "webpack --watch", "lint": "tslint -c tslint.json 'src/**/*.{ts,tsx}'", diff --git a/src/components/__tests__/__snapshots__/counter_spec.tsx.snap b/src/components/__tests__/__snapshots__/counter_spec.tsx.snap index deff78a..24a7858 100644 --- a/src/components/__tests__/__snapshots__/counter_spec.tsx.snap +++ b/src/components/__tests__/__snapshots__/counter_spec.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`components/Counter renders 1`] = ` -): ConnectedDispa dispatch(saveCount({ value })), }) -class CounterComponent extends React.Component { +class PureCounter extends React.Component { _onClickIncrement = (e: React.SyntheticEvent) => { e.preventDefault() @@ -86,5 +88,12 @@ class CounterComponent extends React.Component + p.isLoading || p.isSaving + +// Invoke `loadable` manually pending decorator support +// See: https://github.com/Microsoft/TypeScript/issues/4881 +const LoadableCounter = loadable(isLoading)(PureCounter) + // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/8787 -export const Counter: React.ComponentClass = connect(mapStateToProps, mapDispatchToProps)(CounterComponent) +export const Counter = connect(mapStateToProps, mapDispatchToProps)(LoadableCounter) diff --git a/src/decorators/__tests__/__snapshots__/loadable_spec.tsx.snap b/src/decorators/__tests__/__snapshots__/loadable_spec.tsx.snap new file mode 100644 index 0000000..8e75946 --- /dev/null +++ b/src/decorators/__tests__/__snapshots__/loadable_spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`decorators/loadable maps props to loading 1`] = ``; diff --git a/src/decorators/__tests__/loadable_spec.tsx b/src/decorators/__tests__/loadable_spec.tsx new file mode 100644 index 0000000..6a32c3b --- /dev/null +++ b/src/decorators/__tests__/loadable_spec.tsx @@ -0,0 +1,26 @@ +// tslint:disable-next-line no-unused-variable +import * as React from 'react' +import * as TestUtils from 'react-dom/test-utils' +import * as ReactShallowRenderer from 'react-test-renderer/shallow' + +import loadable from '../loadable' + +const TestComponent = () =>
OK
+const LoadableTestComponent = loadable(props => props.isLoading)(TestComponent) + +describe('decorators/loadable', () => { + + it('sets friendly .displayName', () => { + expect(LoadableTestComponent.displayName) + .toEqual('Loadable(TestComponent)') + }) + + it('maps props to loading', () => { + const renderer = new ReactShallowRenderer() + expect(renderer.render().props.children) + .toEqual('Just a moment, please...') + + expect(renderer.render()) + .toMatchSnapshot() + }) +}) diff --git a/src/decorators/loadable.tsx b/src/decorators/loadable.tsx new file mode 100644 index 0000000..9920878 --- /dev/null +++ b/src/decorators/loadable.tsx @@ -0,0 +1,16 @@ +import * as React from 'react' + +export default function loadable

(isLoading: (p: P) => boolean) { + return (C: React.ComponentClass

|React.SFC

): React.SFC

=> { + const LoadableComponent: React.SFC

= (props) => { + if (isLoading(props)) { + return

Just a moment, please...
+ } + return + } + + // Set pretty `displayName` for dev tooling + LoadableComponent.displayName = `Loadable(${C.name})` + return LoadableComponent + } +}