fix: show error if an action was not handled

This commit is contained in:
Satyajit Sahoo
2019-12-25 02:19:21 +01:00
parent 282f62c258
commit 0252bdc222
5 changed files with 33 additions and 5 deletions

View File

@@ -2,7 +2,7 @@ const error = console.error;
console.error = (...args) =>
// Supress error messages regarding error boundary in tests
/Consider adding an error boundary to your tree to customize error handling behavior/m.test(
/(Consider adding an error boundary to your tree to customize error handling behavior|React will try to recreate this component tree from scratch using the error boundary you provided|Error boundaries should implement getDerivedStateFromError)/m.test(
args[0]
)
? void 0

View File

@@ -357,6 +357,8 @@ it("doesn't update state if action wasn't handled", () => {
const onStateChange = jest.fn();
const spy = jest.spyOn(console, 'error').mockImplementation();
render(
<NavigationContainer onStateChange={onStateChange}>
<TestNavigator initialRouteName="foo">
@@ -367,6 +369,12 @@ it("doesn't update state if action wasn't handled", () => {
);
expect(onStateChange).toBeCalledTimes(0);
expect(spy.mock.calls[0][0]).toMatch(
"The action 'INVALID' with payload 'undefined' was not handled by any navigator."
);
spy.mockRestore();
});
it('cleans up state when the navigator unmounts', () => {

View File

@@ -305,8 +305,7 @@ it("action doesn't bubble if target is specified", () => {
expect(onStateChange).not.toBeCalled();
});
// eslint-disable-next-line jest/expect-expect
it("doesn't crash if no navigator handled the action", () => {
it('logs error if no navigator handled the action', () => {
const TestRouter = MockRouter;
const TestNavigator = (props: any) => {
@@ -366,5 +365,13 @@ it("doesn't crash if no navigator handled the action", () => {
</NavigationContainer>
);
const spy = jest.spyOn(console, 'error').mockImplementation();
render(element).update(element);
expect(spy.mock.calls[0][0]).toMatch(
"The action 'UNKNOWN' with payload 'undefined' was not handled by any navigator."
);
spy.mockRestore();
});

View File

@@ -71,6 +71,10 @@ export type NavigationAction = {
* Type of the action (e.g. `NAVIGATE`)
*/
type: string;
/**
* Additional data for the action
*/
payload?: object;
/**
* Key of the route which dispatched this action.
*/

View File

@@ -42,13 +42,22 @@ export default function useNavigationHelpers<
const { performTransaction } = React.useContext(NavigationStateContext);
return React.useMemo(() => {
const dispatch = (action: Action | ((state: State) => Action)) =>
const dispatch = (action: Action | ((state: State) => Action)) => {
performTransaction(() => {
const payload =
typeof action === 'function' ? action(getState()) : action;
onAction(payload);
const handled = onAction(payload);
if (!handled && process.env.NODE_ENV !== 'production') {
console.error(
`The action '${payload.type}' with payload '${JSON.stringify(
payload.payload
)}' was not handled by any navigator.`
);
}
});
};
const actions = {
...router.actionCreators,