diff --git a/src/components/UIView.tsx b/src/components/UIView.tsx index 7e7ba004..a76419e6 100644 --- a/src/components/UIView.tsx +++ b/src/components/UIView.tsx @@ -152,7 +152,10 @@ class View extends Component { // only class components can implement the // uiCanExit hook and ref doesn't work on // stateless function components - if (typeof component !== 'string' && !!component.prototype.render) { + if ( + typeof component !== 'string' && + (!!component.render || (component.prototype && !!component.prototype.render)) + ) { props.ref = c => { this.componentInstance = c; this.registerUiCanExitHook(stateName); diff --git a/src/components/__tests__/UIView.test.tsx b/src/components/__tests__/UIView.test.tsx index 26d74dad..04643f3e 100644 --- a/src/components/__tests__/UIView.test.tsx +++ b/src/components/__tests__/UIView.test.tsx @@ -245,6 +245,40 @@ describe('', () => { expect(uiCanExitSpy).toBeCalled(); }); + it('calls uiCanExit function of a React.forwardRef() State Component when unmounting', async () => { + let uiCanExitSpy = jest.fn(); + class Comp extends React.Component { + uiCanExit = uiCanExitSpy; + render() { + return UiCanExitHookComponent; + } + } + const ForwardRef = React.forwardRef((props, ref) => ); + const Exit = () => exit; + router = new UIRouterReact(); + router.plugin(servicesPlugin); + router.plugin(memoryLocationPlugin); + router.stateRegistry.register({ + name: '__state', + component: ForwardRef, + } as ReactStateDeclaration); + router.stateRegistry.register({ + name: 'exit', + component: Exit, + } as ReactStateDeclaration); + const wrapper = mount( + + + + ); + await router.stateService.go('__state'); + console.log(wrapper.html()); + expect(wrapper.html()).toEqual('UiCanExitHookComponent'); + await router.stateService.go('exit'); + expect(wrapper.html()).toEqual('exit'); + expect(uiCanExitSpy).toBeCalled(); + }); + it('deregisters the UIView when unmounted', () => { const Component = props => {props.show ? :
}; const wrapper = mount();