feat: respect key when reseting state

This commit is contained in:
satyajit.happy
2019-06-10 16:37:19 +02:00
parent 67b09da633
commit bf958e3c91
5 changed files with 103 additions and 55 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 };
}

View File

@@ -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

View File

@@ -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);