Skip to content

Commit cf5c668

Browse files
fix(uiview): Fix uiCanExit when routing to a React.forwardRef()
1 parent e314bbb commit cf5c668

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

src/components/UIView.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ class View extends Component<UIViewProps, UIViewState> {
152152
// only class components can implement the
153153
// uiCanExit hook and ref doesn't work on
154154
// stateless function components
155-
if (typeof component !== 'string' && !!component.prototype.render) {
155+
if (
156+
typeof component !== 'string' &&
157+
(!!component.render || (component.prototype && !!component.prototype.render))
158+
) {
156159
props.ref = c => {
157160
this.componentInstance = c;
158161
this.registerUiCanExitHook(stateName);

src/components/__tests__/UIView.test.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,40 @@ describe('<UIView>', () => {
245245
expect(uiCanExitSpy).toBeCalled();
246246
});
247247

248+
it('calls uiCanExit function of a React.forwardRef() State Component when unmounting', async () => {
249+
let uiCanExitSpy = jest.fn();
250+
class Comp extends React.Component<any, any> {
251+
uiCanExit = uiCanExitSpy;
252+
render() {
253+
return <span>UiCanExitHookComponent</span>;
254+
}
255+
}
256+
const ForwardRef = React.forwardRef((props, ref) => <Comp {...props} ref={ref} />);
257+
const Exit = () => <span>exit</span>;
258+
router = new UIRouterReact();
259+
router.plugin(servicesPlugin);
260+
router.plugin(memoryLocationPlugin);
261+
router.stateRegistry.register({
262+
name: '__state',
263+
component: ForwardRef,
264+
} as ReactStateDeclaration);
265+
router.stateRegistry.register({
266+
name: 'exit',
267+
component: Exit,
268+
} as ReactStateDeclaration);
269+
const wrapper = mount(
270+
<UIRouter router={router}>
271+
<UIView />
272+
</UIRouter>
273+
);
274+
await router.stateService.go('__state');
275+
console.log(wrapper.html());
276+
expect(wrapper.html()).toEqual('<span>UiCanExitHookComponent</span>');
277+
await router.stateService.go('exit');
278+
expect(wrapper.html()).toEqual('<span>exit</span>');
279+
expect(uiCanExitSpy).toBeCalled();
280+
});
281+
248282
it('deregisters the UIView when unmounted', () => {
249283
const Component = props => <UIRouter router={router}>{props.show ? <UIView /> : <div />}</UIRouter>;
250284
const wrapper = mount(<Component show={true} />);

0 commit comments

Comments
 (0)