diff --git a/src/hooks/__tests__/useIsActive.test.tsx b/src/hooks/__tests__/useIsActive.test.tsx
index 168b4841..1eb05e7f 100644
--- a/src/hooks/__tests__/useIsActive.test.tsx
+++ b/src/hooks/__tests__/useIsActive.test.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import { RawParams } from '@uirouter/core';
import { makeTestRouter } from '../../__tests__/util';
+import { UIView } from '../../components';
import { useIsActive } from '../useIsActive';
const state1 = { name: 'state1', url: '/state1' };
@@ -52,6 +53,24 @@ describe('useIsActive', () => {
expect(wrapper.find('div').props().className).toBe('notactive');
});
+ it('works with relative states', async () => {
+ const parent = { name: 'parent', component: () => };
+ const child = { name: 'parent.child', component: () =>
};
+ router.stateRegistry.register(parent);
+ router.stateRegistry.register(child);
+ await routerGo('parent');
+ const wrapper = mountInRouter();
+ expect(wrapper.find('div').props().className).toBe('notactive');
+
+ await routerGo('parent.child');
+ expect(
+ wrapper
+ .update()
+ .find('div')
+ .props().className
+ ).toBe('yesactive');
+ });
+
it('updates when the desired state changes', async () => {
await routerGo('state2');
const wrapper = mountInRouter();
diff --git a/src/hooks/useIsActive.ts b/src/hooks/useIsActive.ts
index d29d8557..3dc8c573 100644
--- a/src/hooks/useIsActive.ts
+++ b/src/hooks/useIsActive.ts
@@ -1,28 +1,39 @@
-import { StateService } from '@uirouter/core';
+import { StateDeclaration } from '@uirouter/core';
import { useEffect, useMemo, useState } from 'react';
+import { UIRouterReact } from '../core';
import { useDeepObjectDiff } from './useDeepObjectDiff';
import { useOnStateChanged } from './useOnStateChanged';
import { useRouter } from './useRouter';
+import { useViewContextState } from './useViewContextState';
-function checkIfActive(stateService: StateService, stateName: string, params: object, exact: boolean) {
- return exact ? stateService.is(stateName, params) : stateService.includes(stateName, params);
+function checkIfActive(
+ router: UIRouterReact,
+ stateName: string,
+ params: object,
+ relative: StateDeclaration,
+ exact: boolean
+) {
+ return exact
+ ? router.stateService.is(stateName, params, { relative })
+ : router.stateService.includes(stateName, params, { relative });
}
export function useIsActive(stateName: string, params = null, exact = false) {
- const { stateService } = useRouter();
+ const router = useRouter();
+ const relative = useViewContextState(router);
// Don't re-compute initialIsActive on every render
- const initialIsActive = useMemo(() => checkIfActive(stateService, stateName, params, exact), []);
+ const initialIsActive = useMemo(() => checkIfActive(router, stateName, params, relative, exact), []);
const [isActive, setIsActive] = useState(initialIsActive);
const checkIfActiveChanged = () => {
- const newIsActive = checkIfActive(stateService, stateName, params, exact);
+ const newIsActive = checkIfActive(router, stateName, params, relative, exact);
if (newIsActive !== isActive) {
setIsActive(newIsActive);
}
};
useOnStateChanged(checkIfActiveChanged);
- useEffect(checkIfActiveChanged, [stateService, stateName, useDeepObjectDiff(params), exact]);
+ useEffect(checkIfActiveChanged, [router, stateName, useDeepObjectDiff(params), exact]);
return isActive;
}