mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-06-17 05:29:37 +08:00
fix: throw a descriptive error if navigation object hasn't initialized
This commit is contained in:
@@ -22,6 +22,9 @@ type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||
const MISSING_CONTEXT_ERROR =
|
||||
"We couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/en/getting-started.html for setup instructions.";
|
||||
|
||||
const NOT_INITIALIZED_ERROR =
|
||||
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. You can ensure that all navigators have mounted after the callback to 'useEffect' is called in your root component.";
|
||||
|
||||
export const NavigationStateContext = React.createContext<{
|
||||
isDefault?: true;
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
@@ -195,10 +198,18 @@ const BaseNavigationContainer = React.forwardRef(
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: NavigationState) => NavigationAction)
|
||||
) => {
|
||||
if (listeners[0] == null) {
|
||||
throw new Error(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
|
||||
listeners[0](navigation => navigation.dispatch(action));
|
||||
};
|
||||
|
||||
const canGoBack = () => {
|
||||
if (listeners[0] == null) {
|
||||
throw new Error(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
|
||||
const { result, handled } = listeners[0](navigation =>
|
||||
navigation.canGoBack()
|
||||
);
|
||||
|
||||
@@ -501,3 +501,51 @@ it('emits state events when the state changes', () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('throws if there is no navigator rendered', () => {
|
||||
expect.assertions(1);
|
||||
|
||||
const ref = React.createRef<NavigationContainerRef>();
|
||||
|
||||
const element = <BaseNavigationContainer ref={ref} children={null} />;
|
||||
|
||||
render(element);
|
||||
|
||||
act(() => {
|
||||
expect(() => ref.current?.dispatch({ type: 'WHATEVER' })).toThrow(
|
||||
"The 'navigation' object hasn't been initialized yet."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("throws if the ref hasn't finished initializing", () => {
|
||||
expect.assertions(1);
|
||||
|
||||
const ref = React.createRef<NavigationContainerRef>();
|
||||
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return descriptors[state.routes[state.index].key].render();
|
||||
};
|
||||
|
||||
const TestScreen = () => {
|
||||
React.useEffect(() => {
|
||||
expect(() => ref.current?.dispatch({ type: 'WHATEVER' })).toThrow(
|
||||
"The 'navigation' object hasn't been initialized yet."
|
||||
);
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<BaseNavigationContainer ref={ref}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={TestScreen} />
|
||||
</TestNavigator>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user