Skip to content
This repository has been archived by the owner on Feb 8, 2020. It is now read-only.

Commit

Permalink
fix: fire blur event when a route is removed with a delay
Browse files Browse the repository at this point in the history
closes #110
  • Loading branch information
satya164 committed Sep 24, 2019
1 parent 76de32f commit 1153d55
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 13 deletions.
126 changes: 126 additions & 0 deletions packages/core/src/__tests__/useEventEmitter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useNavigationBuilder from '../useNavigationBuilder';
import NavigationContainer from '../NavigationContainer';
import Screen from '../Screen';
import MockRouter from './__fixtures__/MockRouter';
import { Router, NavigationState } from '../types';

it('fires focus and blur events in root navigator', () => {
const TestNavigator = React.forwardRef((props: any, ref: any): any => {
Expand Down Expand Up @@ -200,6 +201,131 @@ it('fires focus and blur events in nested navigator', () => {
expect(thirdFocusCallback).toBeCalledTimes(1);
});

it('fires blur event when a route is removed with a delay', async () => {
const TestRouter = (options: any): Router<NavigationState, any> => {
const router = MockRouter(options);

return {
...router,

getInitialState({ routeNames, routeParamList }) {
const initialRouteName =
options.initialRouteName !== undefined
? options.initialRouteName
: routeNames[0];

return {
stale: false,
key: 'stack',
index: 0,
routeNames,
routes: [
{
key: initialRouteName,
name: initialRouteName,
params: routeParamList[initialRouteName],
},
],
};
},

getStateForAction(state, action) {
switch (action.type) {
case 'PUSH':
return {
...state,
index: state.index + 1,
routes: [...state.routes, action.payload],
};
case 'POP': {
const routes = state.routes.slice(0, -1);

return {
...state,
index: routes.length - 1,
routes,
};
}
default:
return router.getStateForAction(state, action);
}
},

actionCreators: {
push(payload) {
return { type: 'PUSH', payload };
},

pop() {
return { type: 'POP' };
},
},
};
};

const TestNavigator = React.forwardRef((props: any, ref: any): any => {
const { state, navigation, descriptors } = useNavigationBuilder(
TestRouter,
props
);

React.useImperativeHandle(ref, () => navigation, [navigation]);

const [previous, dispatch] = React.useReducer(
(state, action) => {
return { ...state, ...action };
},
{ routes: state.routes, descriptors }
);

React.useEffect(() => {
dispatch({ routes: state.routes, descriptors });
}, [descriptors, state.routes]);

return previous.routes.map((route: any) =>
previous.descriptors[route.key].render()
);
});

const blurCallback = jest.fn();

const First = () => null;

const Second = ({ navigation }: any) => {
React.useEffect(() => navigation.addListener('blur', blurCallback), [
navigation,
]);

return null;
};

const navigation = React.createRef<any>();

const element = (
<NavigationContainer>
<TestNavigator ref={navigation}>
<Screen name="first" component={First} />
<Screen name="second" component={Second} />
</TestNavigator>
</NavigationContainer>
);

render(element);

act(() =>
navigation.current.push({
name: 'second',
key: 'second',
})
);

expect(blurCallback).toBeCalledTimes(0);

act(() => navigation.current.pop());

expect(blurCallback).toBeCalledTimes(1);
});

it('fires custom events', () => {
const eventName = 'someSuperCoolEvent';

Expand Down
26 changes: 13 additions & 13 deletions packages/core/src/useFocusEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ export default function useFocusEvents({ state, emitter }: Options) {
return;
}

state.routes.forEach((route, i) => {
if (
lastFocusedKey === undefined ||
(route.key !== lastFocusedKey && route.key !== currentFocusedKey)
) {
// Only fire events after mount, or if focus state of this route changed
return;
}
if (lastFocusedKey === undefined) {
// Only fire events after initial mount
return;
}

emitter.emit({
type: 'focus',
target: currentFocusedKey,
});

emitter.emit({
type: i === state.index ? 'focus' : 'blur',
target: route.key,
});
emitter.emit({
type: 'blur',
target: lastFocusedKey,
});
}, [currentFocusedKey, emitter, navigation, state.index, state.routes]);
}, [currentFocusedKey, emitter, navigation]);
}

0 comments on commit 1153d55

Please sign in to comment.