diff --git a/src/rxreact.tsx b/src/rxreact.tsx index e2f2da6..9204bdd 100644 --- a/src/rxreact.tsx +++ b/src/rxreact.tsx @@ -30,7 +30,7 @@ function withViewModelFactory>( constructor(props: Difference>) { super(props); let viewModel = viewModelFactory(this.propsObservable); - this.observableState = combineObservables(viewModel.inputs); + this.observableState = Object.keys(viewModel.inputs).length ? combineObservables(viewModel.inputs) : Observable.of({} as S); this.actions = subjectMapToActionMap(viewModel.outputs); } diff --git a/test/rxreact.test.tsx b/test/rxreact.test.tsx index 48b0031..eb1aa6a 100644 --- a/test/rxreact.test.tsx +++ b/test/rxreact.test.tsx @@ -106,6 +106,50 @@ describe("withViewModel", () => { expect(rendered.find("#other").text()).toContain("moldy cheese"); }); }); + + describe("when `inputs` are empty", () => { + it("still renders", () => { + interface OutputOnlyComponentProps { + inputNumber: (_: number) => void; + } + let Component: React.SFC = () => +
Just checking
; + let viewModel = { + inputs: {}, + outputs: {inputNumber: numberSubject} + }; + let ComponentWithViewModel = withViewModel(viewModel, Component); + const subject = mount(); + + expect(subject.text()).toEqual("Just checking"); + }); + }); + + describe("when `outputs` are empty", () => { + it("still renders", () => { + interface InputOnlyComponentProps { + derived1: string; + derived2: string; + } + + let Component: React.SFC = ({ + derived1, + derived2, + }) => +
We have {derived1} {derived2}
; + let viewModel = { + inputs: { + derived1: derived1Signal, + derived2: derived2Signal, + }, + outputs: {} + }; + let ComponentWithViewModel = withViewModel(viewModel, Component); + const subject = mount(); + + expect(subject.text()).toEqual("We have 2 bananas applesauce"); + }); + }); }); describe("with a view model that has no initial value for state", () => {