mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-06-16 21:21:27 +08:00
fix: throw when containers are nested within another
This commit is contained in:
@@ -23,6 +23,7 @@ const MISSING_CONTEXT_ERROR =
|
||||
"We couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'?";
|
||||
|
||||
export const NavigationStateContext = React.createContext<{
|
||||
isDefault?: true;
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
getState: () => NavigationState | PartialState<NavigationState> | undefined;
|
||||
setState: (
|
||||
@@ -31,6 +32,8 @@ export const NavigationStateContext = React.createContext<{
|
||||
key?: string;
|
||||
performTransaction: (action: () => void) => void;
|
||||
}>({
|
||||
isDefault: true,
|
||||
|
||||
get getState(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
@@ -83,9 +86,22 @@ const getPartialState = (
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const Container = React.forwardRef(function NavigationContainer(
|
||||
{ initialState, onStateChange, children }: NavigationContainerProps,
|
||||
{
|
||||
initialState,
|
||||
onStateChange,
|
||||
independent,
|
||||
children,
|
||||
}: NavigationContainerProps,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const parent = React.useContext(NavigationStateContext);
|
||||
|
||||
if (!parent.isDefault && !independent) {
|
||||
throw new Error(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitely."
|
||||
);
|
||||
}
|
||||
|
||||
const [state, setNavigationState] = React.useState<State>(() =>
|
||||
getPartialState(initialState == null ? undefined : initialState)
|
||||
);
|
||||
|
||||
@@ -122,6 +122,32 @@ it('throws when nesting performTransaction', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when nesting containers', () => {
|
||||
expect(() =>
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<NavigationContainer>
|
||||
<React.Fragment />
|
||||
</NavigationContainer>
|
||||
</NavigationContainer>
|
||||
)
|
||||
).toThrowError(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another."
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<NavigationContainer independent>
|
||||
<React.Fragment />
|
||||
</NavigationContainer>
|
||||
</NavigationContainer>
|
||||
)
|
||||
).not.toThrowError(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another."
|
||||
);
|
||||
});
|
||||
|
||||
it('handle dispatching with ref', () => {
|
||||
const CurrentParentRouter = MockRouter;
|
||||
|
||||
|
||||
@@ -377,10 +377,23 @@ export type NavigationHelpers<
|
||||
};
|
||||
|
||||
export type NavigationContainerProps = {
|
||||
/**
|
||||
* Initial navigation state for the child navigators.
|
||||
*/
|
||||
initialState?: InitialState;
|
||||
onStateChange?: (
|
||||
state: NavigationState | PartialState<NavigationState> | undefined
|
||||
) => void;
|
||||
/**
|
||||
* Callback which is called with the latest navigation state when it changes.
|
||||
*/
|
||||
onStateChange?: (state: NavigationState | undefined) => void;
|
||||
/**
|
||||
* Whether this navigation container should be independent of parent containers.
|
||||
* If this is not set to `true`, this container cannot be nested inside another container.
|
||||
* Setting it to `true` disconnects any children navigators from parent container.
|
||||
*/
|
||||
independent?: boolean;
|
||||
/**
|
||||
* Children elements to render.
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user