mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-12 22:51:18 +08:00
feat: add dangerouslyGetState (#63)
This commit is contained in:
@@ -4,6 +4,8 @@ import Screen from '../Screen';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
import useNavigation from '../useNavigation';
|
||||
import { NavigationState } from '../types';
|
||||
|
||||
beforeEach(() => (MockRouterKey.current = 0));
|
||||
|
||||
@@ -467,6 +469,7 @@ it('updates route params with setParams applied to parent', () => {
|
||||
{ key: 'foo', name: 'foo', params: { username: 'alice' } },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
],
|
||||
stale: false,
|
||||
});
|
||||
|
||||
act(() => setParams({ age: 25 }));
|
||||
@@ -480,6 +483,7 @@ it('updates route params with setParams applied to parent', () => {
|
||||
{ key: 'foo', name: 'foo', params: { username: 'alice', age: 25 } },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
],
|
||||
stale: false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -519,6 +523,40 @@ it('handles change in route names', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('gives access to internal state', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return descriptors[state.routes[state.index].key].render();
|
||||
};
|
||||
|
||||
let state: NavigationState | undefined;
|
||||
|
||||
const Test = () => {
|
||||
const navigation = useNavigation();
|
||||
state = navigation.dangerouslyGetState();
|
||||
return null;
|
||||
};
|
||||
|
||||
const root = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator initialRouteName="bar">
|
||||
<Screen name="bar" component={Test} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
render(root).update(root);
|
||||
|
||||
expect(state).toEqual({
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['bar'],
|
||||
routes: [{ key: 'bar', name: 'bar' }],
|
||||
stale: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("throws if navigator doesn't have any screens", () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
|
||||
@@ -377,6 +377,13 @@ export type NavigationProp<
|
||||
dangerouslyGetParent():
|
||||
| NavigationProp<ParamListBase, string, any, any>
|
||||
| undefined;
|
||||
|
||||
/**
|
||||
* Returns the navigator's state. Reason why the function is called
|
||||
* dangerouslyGetState is to discourage developers to use internal navigation's state.
|
||||
* Note that this method doesn't re-render screen when the result changes. So don't use it in `render`.
|
||||
*/
|
||||
dangerouslyGetState(): State;
|
||||
} & EventConsumer<EventMap & EventMapBase> &
|
||||
PrivateValueStore<ParamList, RouteName, EventMap>;
|
||||
|
||||
|
||||
@@ -43,10 +43,12 @@ export default function useNavigationCache<
|
||||
// Cache object which holds navigation objects for each screen
|
||||
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
|
||||
// In reality, these deps will rarely change, if ever
|
||||
const parentNavigation = React.useContext(NavigationContext);
|
||||
|
||||
const cache = React.useMemo(
|
||||
() => ({ current: {} as NavigationCache<State, ScreenOptions> }),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[getState, navigation, setOptions, router, emitter]
|
||||
[getState, navigation, setOptions, router, emitter, parentNavigation]
|
||||
);
|
||||
|
||||
const actions = {
|
||||
@@ -54,8 +56,6 @@ export default function useNavigationCache<
|
||||
...BaseActions,
|
||||
};
|
||||
|
||||
const parentNavigation = React.useContext(NavigationContext);
|
||||
|
||||
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
|
||||
(acc, route, index) => {
|
||||
const previous = cache.current[route.key];
|
||||
@@ -92,6 +92,7 @@ export default function useNavigationCache<
|
||||
...helpers,
|
||||
...emitter.create(route.key),
|
||||
dangerouslyGetParent: () => parentNavigation,
|
||||
dangerouslyGetState: getState as () => State,
|
||||
dispatch,
|
||||
setOptions: (options: object) =>
|
||||
setOptions(o => ({
|
||||
|
||||
Reference in New Issue
Block a user