mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-12 22:51:18 +08:00
refactor: check for stale == false to determine if state is rehydrated
This commit is contained in:
@@ -306,12 +306,10 @@ For example, the path `/rooms/chat?user=jane` will be translated to a state obje
|
||||
|
||||
```js
|
||||
{
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'rooms',
|
||||
state: {
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'chat',
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as BaseActions from '../BaseActions';
|
||||
jest.mock('shortid', () => () => 'test');
|
||||
|
||||
const STATE = {
|
||||
stale: false as false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
@@ -21,6 +22,7 @@ it('replaces focused screen with REPLACE', () => {
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
@@ -39,6 +41,7 @@ it('replaces source screen with REPLACE', () => {
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
@@ -66,6 +69,7 @@ it('sets params for the focused screen with SET_PARAMS', () => {
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
@@ -84,6 +88,7 @@ it('sets params for the source screen with SET_PARAMS', () => {
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
|
||||
@@ -296,7 +296,6 @@ it('handle resetting state with ref', () => {
|
||||
render(element).update(element);
|
||||
|
||||
const state = {
|
||||
stale: true,
|
||||
index: 1,
|
||||
routes: [
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
: routeNames.indexOf(options.initialRouteName);
|
||||
|
||||
return {
|
||||
stale: false,
|
||||
key: String(MockRouterKey.current++),
|
||||
index,
|
||||
routeNames,
|
||||
@@ -34,7 +35,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
getRehydratedState(partialState, { routeNames, routeParamList }) {
|
||||
let state = partialState;
|
||||
|
||||
if (!state.stale) {
|
||||
if (state.stale === false) {
|
||||
return state as NavigationState;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,14 @@ it('converts path string to initial state', () => {
|
||||
'foo/bar/baz%20qux?author=%22jane%20%26%20co%22&valid=true'
|
||||
)
|
||||
).toEqual({
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'foo',
|
||||
state: {
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'bar',
|
||||
state: {
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'baz qux',
|
||||
@@ -34,12 +31,10 @@ it('converts path string to initial state', () => {
|
||||
|
||||
it('handles leading slash when converting', () => {
|
||||
expect(getStateFromPath('/foo/bar/?count=42')).toEqual({
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'foo',
|
||||
state: {
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'bar',
|
||||
@@ -54,12 +49,10 @@ it('handles leading slash when converting', () => {
|
||||
|
||||
it('handles ending slash when converting', () => {
|
||||
expect(getStateFromPath('foo/bar/?count=42')).toEqual({
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'foo',
|
||||
state: {
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'bar',
|
||||
@@ -74,12 +67,10 @@ it('handles ending slash when converting', () => {
|
||||
|
||||
it('handles route without param', () => {
|
||||
expect(getStateFromPath('foo/bar')).toEqual({
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'foo',
|
||||
state: {
|
||||
stale: true,
|
||||
routes: [{ name: 'bar' }],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -49,6 +49,7 @@ it('initializes state for a navigator on navigation', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).toBeCalledWith({
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar', 'baz'],
|
||||
@@ -140,6 +141,7 @@ it('initializes state for nested screens in React.Fragment', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).toBeCalledWith({
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar', 'baz'],
|
||||
@@ -189,6 +191,7 @@ it('initializes state for nested navigator on navigation', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).toBeCalledWith({
|
||||
stale: false,
|
||||
index: 2,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar', 'baz'],
|
||||
@@ -199,6 +202,7 @@ it('initializes state for nested navigator on navigation', () => {
|
||||
key: 'baz',
|
||||
name: 'baz',
|
||||
state: {
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '1',
|
||||
routeNames: ['qux'],
|
||||
@@ -302,6 +306,7 @@ it('cleans up state when the navigator unmounts', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).lastCalledWith({
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar'],
|
||||
@@ -353,6 +358,7 @@ it('allows arbitrary state updates by dispatching a function', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).toBeCalledWith({
|
||||
stale: false,
|
||||
index: 1,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar'],
|
||||
@@ -390,6 +396,7 @@ it('updates route params with setParams', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).lastCalledWith({
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar'],
|
||||
@@ -403,6 +410,7 @@ it('updates route params with setParams', () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(2);
|
||||
expect(onStateChange).lastCalledWith({
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar'],
|
||||
@@ -441,6 +449,7 @@ it('handles change in route names', () => {
|
||||
);
|
||||
|
||||
expect(onStateChange).toBeCalledWith({
|
||||
stale: false,
|
||||
index: 0,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'baz', 'qux'],
|
||||
|
||||
@@ -75,6 +75,7 @@ it("lets parent handle the action if child didn't", () => {
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).lastCalledWith({
|
||||
stale: false,
|
||||
index: 2,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar', 'baz'],
|
||||
|
||||
@@ -18,7 +18,6 @@ export default function getStateFromPath(
|
||||
|
||||
while (segments.length) {
|
||||
const state = {
|
||||
stale: true,
|
||||
routes: [{ name: decodeURIComponent(segments[0]) }],
|
||||
};
|
||||
|
||||
|
||||
@@ -24,20 +24,19 @@ export type NavigationState = {
|
||||
/**
|
||||
* Whether the navigation state has been rehydrated.
|
||||
*/
|
||||
stale?: false;
|
||||
stale: false;
|
||||
};
|
||||
|
||||
export type InitialState = Partial<
|
||||
Omit<NavigationState, 'stale' | 'routes'>
|
||||
> & {
|
||||
stale?: boolean;
|
||||
routes: Array<Omit<Route<string>, 'key'> & { state?: InitialState }>;
|
||||
};
|
||||
|
||||
export type PartialState<State extends NavigationState> = Partial<
|
||||
Omit<State, 'stale' | 'key' | 'routes' | 'routeNames'>
|
||||
> & {
|
||||
stale?: boolean;
|
||||
stale?: true;
|
||||
routes: Array<
|
||||
Omit<Route<string>, 'key'> & { key?: string; state?: InitialState }
|
||||
>;
|
||||
@@ -128,7 +127,7 @@ export type Router<
|
||||
* @param options.routeParamsList Object containing params for each route.
|
||||
*/
|
||||
getRehydratedState(
|
||||
partialState: PartialState<State>,
|
||||
partialState: PartialState<State> | State,
|
||||
options: {
|
||||
routeNames: string[];
|
||||
routeParamList: ParamListBase;
|
||||
|
||||
@@ -162,7 +162,7 @@ export default function useNavigationBuilder<
|
||||
// If the state isn't initialized, or stale, use the state we initialized instead
|
||||
// The state won't update until there's a change needed in the state we have initalized locally
|
||||
// So it'll be `undefined` or stale untill the first navigation event happens
|
||||
currentState === undefined || currentState.stale
|
||||
currentState === undefined || currentState.stale !== false
|
||||
? (initializedStateRef.current as State)
|
||||
: (currentState as State);
|
||||
|
||||
@@ -201,7 +201,7 @@ export default function useNavigationBuilder<
|
||||
const getState = React.useCallback((): State => {
|
||||
const currentState = getCurrentState();
|
||||
|
||||
return currentState === undefined || currentState.stale
|
||||
return currentState === undefined || currentState.stale !== false
|
||||
? (initializedStateRef.current as State)
|
||||
: (currentState as State);
|
||||
}, [getCurrentState]);
|
||||
|
||||
@@ -72,13 +72,11 @@ export default function App() {
|
||||
const state = getStateFromPath(path);
|
||||
|
||||
return {
|
||||
stale: true,
|
||||
routes: [
|
||||
{
|
||||
name: 'root',
|
||||
state: {
|
||||
...state,
|
||||
stale: true,
|
||||
routes: [{ name: 'home' }, ...(state ? state.routes : [])],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -55,6 +55,7 @@ export default function DrawerRouter(
|
||||
: routeNames.indexOf(options.initialRouteName);
|
||||
|
||||
return {
|
||||
stale: false,
|
||||
key: `drawer-${shortid()}`,
|
||||
index,
|
||||
routeNames,
|
||||
@@ -69,8 +70,8 @@ export default function DrawerRouter(
|
||||
},
|
||||
|
||||
getRehydratedState(partialState, { routeNames, routeParamList }) {
|
||||
if (!partialState.stale) {
|
||||
return partialState as DrawerNavigationState;
|
||||
if (partialState.stale === false) {
|
||||
return partialState;
|
||||
}
|
||||
|
||||
const state = router.getRehydratedState(partialState, {
|
||||
|
||||
@@ -54,6 +54,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
: routeNames[0];
|
||||
|
||||
return {
|
||||
stale: false,
|
||||
key: `stack-${shortid()}`,
|
||||
index: 0,
|
||||
routeNames,
|
||||
@@ -70,8 +71,8 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
getRehydratedState(partialState, { routeNames, routeParamList }) {
|
||||
let state = partialState;
|
||||
|
||||
if (!state.stale) {
|
||||
return state as StackNavigationState;
|
||||
if (state.stale === false) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const routes = state.routes
|
||||
|
||||
@@ -2,6 +2,7 @@ import shortid from 'shortid';
|
||||
import {
|
||||
CommonAction,
|
||||
BaseRouter,
|
||||
PartialState,
|
||||
NavigationState,
|
||||
DefaultRouterOptions,
|
||||
Router,
|
||||
@@ -60,6 +61,7 @@ export default function TabRouter({
|
||||
: routeNames.indexOf(initialRouteName);
|
||||
|
||||
return {
|
||||
stale: false,
|
||||
key: `tab-${shortid()}`,
|
||||
index,
|
||||
routeNames,
|
||||
@@ -75,12 +77,14 @@ export default function TabRouter({
|
||||
getRehydratedState(partialState, { routeNames, routeParamList }) {
|
||||
let state = partialState;
|
||||
|
||||
if (!state.stale) {
|
||||
return state as TabNavigationState;
|
||||
if (state.stale === false) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const routes = routeNames.map(name => {
|
||||
const route = state.routes.find(r => r.name === name);
|
||||
const route = (state as PartialState<TabNavigationState>).routes.find(
|
||||
r => r.name === name
|
||||
);
|
||||
|
||||
return {
|
||||
...route,
|
||||
|
||||
Reference in New Issue
Block a user