mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 17:34:59 +08:00
feat: respect key when reseting state
This commit is contained in:
@@ -26,22 +26,38 @@ type Action =
|
||||
export type StackNavigationProp = NavigationProp<typeof StackRouter>;
|
||||
|
||||
const StackRouter = {
|
||||
initial({
|
||||
normalize({
|
||||
currentState,
|
||||
routeNames,
|
||||
initialRouteName = routeNames[0],
|
||||
}: {
|
||||
currentState?: InitialState | NavigationState;
|
||||
routeNames: string[];
|
||||
initialRouteName?: string;
|
||||
}): InitialState {
|
||||
const index = routeNames.indexOf(initialRouteName);
|
||||
}): NavigationState {
|
||||
let state = currentState;
|
||||
|
||||
return {
|
||||
index,
|
||||
routes: routeNames.slice(0, index + 1).map(name => ({
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
})),
|
||||
};
|
||||
if (state === undefined) {
|
||||
const index = routeNames.indexOf(initialRouteName);
|
||||
|
||||
state = {
|
||||
index,
|
||||
routes: routeNames.slice(0, index + 1).map(name => ({
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
if (state.names === undefined || state.key === undefined) {
|
||||
state = {
|
||||
...state,
|
||||
names: state.names || routeNames,
|
||||
key: state.key || `stack-${shortid()}`,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
|
||||
reduce(
|
||||
@@ -99,8 +115,20 @@ const StackRouter = {
|
||||
? StackRouter.reduce(state, { type: 'POP' })
|
||||
: state;
|
||||
|
||||
case 'RESET':
|
||||
return action.payload;
|
||||
case 'RESET': {
|
||||
if (
|
||||
action.payload.key === undefined ||
|
||||
action.payload.key === state.key
|
||||
) {
|
||||
return {
|
||||
...action.payload,
|
||||
key: state.key,
|
||||
names: state.names,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
|
||||
@@ -24,22 +24,38 @@ type Action = {
|
||||
export type TabNavigationProp = NavigationProp<typeof TabRouter>;
|
||||
|
||||
const TabRouter = {
|
||||
initial({
|
||||
normalize({
|
||||
currentState,
|
||||
routeNames,
|
||||
initialRouteName = routeNames[0],
|
||||
}: {
|
||||
routeNames: string[];
|
||||
currentState?: InitialState | NavigationState;
|
||||
initialRouteName?: string;
|
||||
}): InitialState {
|
||||
const index = routeNames.indexOf(initialRouteName);
|
||||
}): NavigationState {
|
||||
let state = currentState;
|
||||
|
||||
return {
|
||||
index,
|
||||
routes: routeNames.map(name => ({
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
})),
|
||||
};
|
||||
if (state === undefined) {
|
||||
const index = routeNames.indexOf(initialRouteName);
|
||||
|
||||
state = {
|
||||
index,
|
||||
routes: routeNames.map(name => ({
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
if (state.names === undefined || state.key === undefined) {
|
||||
state = {
|
||||
...state,
|
||||
names: state.names || routeNames,
|
||||
key: state.key || `tab-${shortid()}`,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
|
||||
reduce(
|
||||
@@ -80,7 +96,18 @@ const TabRouter = {
|
||||
}
|
||||
|
||||
case 'RESET':
|
||||
return action.payload;
|
||||
if (
|
||||
action.payload.key === undefined ||
|
||||
action.payload.key === state.key
|
||||
) {
|
||||
return {
|
||||
...action.payload,
|
||||
key: state.key,
|
||||
names: state.names,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
case 'GO_BACK':
|
||||
return null;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NavigationState } from './types';
|
||||
import { InitialState } from './types';
|
||||
|
||||
export type Action =
|
||||
| { type: 'GO_BACK' }
|
||||
@@ -8,7 +8,7 @@ export type Action =
|
||||
}
|
||||
| {
|
||||
type: 'RESET';
|
||||
payload: NavigationState;
|
||||
payload: InitialState & { key?: string };
|
||||
};
|
||||
|
||||
export function goBack(): Action {
|
||||
@@ -19,6 +19,6 @@ export function navigate(name: string): Action {
|
||||
return { type: 'NAVIGATE', payload: { name } };
|
||||
}
|
||||
|
||||
export function reset(state: NavigationState): Action {
|
||||
export function reset(state: InitialState & { key?: string }): Action {
|
||||
return { type: 'RESET', payload: state };
|
||||
}
|
||||
|
||||
@@ -3,19 +3,21 @@ import * as BaseActions from './BaseActions';
|
||||
export type CommonAction = BaseActions.Action;
|
||||
|
||||
export type NavigationState = {
|
||||
key: string;
|
||||
index: number;
|
||||
names: string[];
|
||||
routes: Array<Route & { state?: NavigationState }>;
|
||||
};
|
||||
|
||||
export type InitialState = Omit<NavigationState, 'names'> & {
|
||||
export type InitialState = Omit<Omit<NavigationState, 'names'>, 'key'> & {
|
||||
key?: undefined;
|
||||
names?: undefined;
|
||||
state?: InitialState;
|
||||
};
|
||||
|
||||
export type Route = {
|
||||
name: string;
|
||||
key: string;
|
||||
name: string;
|
||||
params?: {};
|
||||
};
|
||||
|
||||
@@ -24,10 +26,12 @@ export type NavigationAction = {
|
||||
};
|
||||
|
||||
export type Router<Action extends NavigationAction = NavigationAction> = {
|
||||
initial(options: {
|
||||
normalize(options: {
|
||||
currentState?: NavigationState | InitialState;
|
||||
routeNames: string[];
|
||||
initialRouteName?: string;
|
||||
}): InitialState;
|
||||
}): NavigationState;
|
||||
|
||||
reduce(
|
||||
state: NavigationState,
|
||||
action: Action | CommonAction
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
NavigationAction,
|
||||
Descriptor,
|
||||
NavigationHelpers,
|
||||
NavigationState,
|
||||
} from './types';
|
||||
import Screen, { Props as ScreenProps } from './Screen';
|
||||
import SceneView from './SceneView';
|
||||
@@ -37,38 +38,26 @@ export default function useNavigationBuilder(router: Router, options: Options) {
|
||||
);
|
||||
|
||||
const routeNames = Object.keys(screens);
|
||||
const initialState = React.useMemo(
|
||||
() => ({
|
||||
...router.initial({
|
||||
routeNames,
|
||||
initialRouteName: options.initialRouteName,
|
||||
}),
|
||||
names: routeNames,
|
||||
}),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[options.initialRouteName, router, ...routeNames]
|
||||
);
|
||||
|
||||
const {
|
||||
state: currentState = initialState,
|
||||
state: currentState = router.normalize({
|
||||
routeNames,
|
||||
initialRouteName: options.initialRouteName,
|
||||
}),
|
||||
getState: getCurrentState,
|
||||
setState,
|
||||
} = React.useContext(NavigationStateContext);
|
||||
|
||||
const getState = React.useCallback(() => {
|
||||
let state = getCurrentState();
|
||||
|
||||
if (state === undefined) {
|
||||
state = initialState;
|
||||
}
|
||||
|
||||
if (state.names === undefined) {
|
||||
state = { ...state, names: routeNames };
|
||||
}
|
||||
|
||||
return state;
|
||||
const getState = React.useCallback(
|
||||
(): NavigationState =>
|
||||
router.normalize({
|
||||
currentState: getCurrentState(),
|
||||
routeNames,
|
||||
initialRouteName: options.initialRouteName,
|
||||
}),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [getCurrentState, initialState, ...routeNames]);
|
||||
[getCurrentState, ...routeNames]
|
||||
);
|
||||
|
||||
const parentNavigationHelpers = React.useContext(NavigationHelpersContext);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user