expo-router 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoRoot.d.ts","sourceRoot":"","sources":["../src/ExpoRoot.tsx"],"names":[],"mappings":"AACA,OAAc,EAAE,iBAAiB,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAMtE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,CAAC,EAAE,iBAAiB,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC;AAgCF,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EAAE,aAAwB,EACjC,GAAG,KAAK,EACT,EAAE,aAAa,eAyBf"}
1
+ {"version":3,"file":"ExpoRoot.d.ts","sourceRoot":"","sources":["../src/ExpoRoot.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,iBAAiB,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAMtE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,CAAC,EAAE,iBAAiB,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC;AAqCF,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EAAE,aAAwB,EACjC,GAAG,KAAK,EACT,EAAE,aAAa,eA2Bf"}
@@ -15,6 +15,7 @@ export declare class RouterStore {
15
15
  rootComponent: ComponentType;
16
16
  linking: ExpoLinkingOptions | undefined;
17
17
  isReady: boolean;
18
+ private hasAttemptedToHideSplash;
18
19
  initialState: ResultState | undefined;
19
20
  rootState: ResultState | undefined;
20
21
  nextState: ResultState | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"router-store.d.ts","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EAGlC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAiC,aAAa,EAAY,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM1C;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAS,EAAG,SAAS,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,aAAa,CAAC;IAC9B,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,OAAO,EAAE,OAAO,CAAS;IAEzB,YAAY,EAAE,WAAW,GAAG,SAAS,CAAC;IACtC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAElC,aAAa,EAAG,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACjF,yBAAyB,EAAG,MAAM,IAAI,CAAC;IAEvC,oBAAoB,YAAiB,IAAI,EAAI;IAC7C,gBAAgB,YAAiB,IAAI,EAAI;IAEzC,MAAM,qDAAqB;IAC3B,eAAe,oBAA8B;IAC7C,MAAM,aAAqB;IAC3B,SAAS,gBAAwB;IACjC,IAAI,6CAAmB;IACvB,OAAO,6CAAsB;IAC7B,SAAS,gEAAwB;IAEjC,UAAU,CACR,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,EAC/E,eAAe,CAAC,EAAE,GAAG;IAgGvB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,cAAQ;IAWjD,YAAY,CAAC,KAAK,EAAE,WAAW;IAgB/B,kBAAkB;IAIlB,uEAAuE;IACvE,OAAO,aAKL;IACF,oBAAoB,eAAgB,MAAM,IAAI,mBAG5C;IACF,gBAAgB,eAAgB,MAAM,IAAI,mBAGxC;IACF,QAAQ,aAEN;IACF,iBAAiB,oBAEf;IACF,iBAAiB,kBAEf;CACH;AAED,eAAO,MAAM,KAAK,aAAoB,CAAC;AAEvC,wBAAgB,aAAa,gBAM5B;AAaD,wBAAgB,iBAAiB,gBAOhC;AAED,wBAAgB,iBAAiB,cAOhC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,cAAc,EACvB,eAAe,EAAE,GAAG,GAAG,SAAS,eASjC"}
1
+ {"version":3,"file":"router-store.d.ts","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EAGlC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAiC,aAAa,EAAY,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM1C;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAS,EAAG,SAAS,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,aAAa,CAAC;IAC9B,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,OAAO,EAAE,OAAO,CAAS;IACzB,OAAO,CAAC,wBAAwB,CAAkB;IAElD,YAAY,EAAE,WAAW,GAAG,SAAS,CAAC;IACtC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAElC,aAAa,EAAG,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACjF,yBAAyB,EAAG,MAAM,IAAI,CAAC;IAEvC,oBAAoB,YAAiB,IAAI,EAAI;IAC7C,gBAAgB,YAAiB,IAAI,EAAI;IAEzC,MAAM,qDAAqB;IAC3B,eAAe,oBAA8B;IAC7C,MAAM,aAAqB;IAC3B,SAAS,gBAAwB;IACjC,IAAI,6CAAmB;IACvB,OAAO,6CAAsB;IAC7B,SAAS,gEAAwB;IAEjC,UAAU,CACR,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,EAC/E,eAAe,CAAC,EAAE,GAAG;IAwGvB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,cAAQ;IAWjD,YAAY,CAAC,KAAK,EAAE,WAAW;IAgB/B,kBAAkB;IAIlB,uEAAuE;IACvE,OAAO,aAEL;IACF,oBAAoB,eAAgB,MAAM,IAAI,mBAG5C;IACF,gBAAgB,eAAgB,MAAM,IAAI,mBAGxC;IACF,QAAQ,aAEN;IACF,iBAAiB,oBAEf;IACF,iBAAiB,kBAEf;CACH;AAED,eAAO,MAAM,KAAK,aAAoB,CAAC;AAEvC,wBAAgB,aAAa,gBAM5B;AAaD,wBAAgB,iBAAiB,gBAOhC;AAED,wBAAgB,iBAAiB,cAOhC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,cAAc,EACvB,eAAe,EAAE,GAAG,GAAG,SAAS,eASjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAEtD,wBAAgB,sBAAsB,kDAErC;AAED,wBAAgB,YAAY,2CAE3B;AAED,wBAAgB,iBAAiB,oGAEhC;AAGD,wBAAgB,OAAO,WAGtB;AAED,wBAAgB,SAAS,IAAI,MAAM,CASlC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CACzB,SAAS,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,KAClC,SAAS,CAEb;AAED,kEAAkE;AAClE,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAC7B,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAEtD,wBAAgB,sBAAsB,kDAErC;AAED,wBAAgB,YAAY,2CAE3B;AAED,wBAAgB,iBAAiB,oGAEhC;AAGD,wBAAgB,OAAO,WAGtB;AAED,wBAAgB,SAAS,IAAI,MAAM,CAYlC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CACzB,SAAS,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,KAClC,SAAS,CAEb;AAED,kEAAkE;AAClE,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAC7B,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"href.d.ts","sourceRoot":"","sources":["../../src/link/href.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,oEAAoE;AACpE,eAAO,MAAM,WAAW,SAAU,IAAI,KAAG,MAexC,CAAC"}
1
+ {"version":3,"file":"href.d.ts","sourceRoot":"","sources":["../../src/link/href.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,oEAAoE;AACpE,eAAO,MAAM,WAAW,SAAU,IAAI,KAAG,MAaxC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tutorial.d.ts","sourceRoot":"","sources":["../../src/onboard/Tutorial.tsx"],"names":[],"mappings":";AAqCA,wBAAgB,QAAQ,gBAyCvB"}
1
+ {"version":3,"file":"Tutorial.d.ts","sourceRoot":"","sources":["../../src/onboard/Tutorial.tsx"],"names":[],"mappings":";AAqCA,wBAAgB,QAAQ,gBAqCvB"}
@@ -0,0 +1,3 @@
1
+ export declare function useWarnOnce(message: string, guard?: unknown, key?: string): void;
2
+ export declare function useDeprecated(message: string, guard?: unknown, key?: string): void;
3
+ //# sourceMappingURL=useDeprecated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeprecated.d.ts","sourceRoot":"","sources":["../src/useDeprecated.ts"],"names":[],"mappings":"AAaA,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,OAAc,EACrB,GAAG,SAAU,QAUd;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,OAAc,EACrB,GAAG,SAAU,QAGd"}
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/views/ErrorBoundary.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAmC3C,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,eA2DjE"}
1
+ {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/views/ErrorBoundary.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAmC3C,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,eAuDjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"Screen.d.ts","sourceRoot":"","sources":["../../src/views/Screen.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IACxD;IACF;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AAKF,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,EACvD,IAAI,EACJ,QAAQ,EACR,OAAO,GACR,EAAE,WAAW,CAAC,QAAQ,CAAC,QAmBvB"}
1
+ {"version":3,"file":"Screen.d.ts","sourceRoot":"","sources":["../../src/views/Screen.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IACxD;IACF;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AAKF,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,EACvD,IAAI,EACJ,QAAQ,EACR,OAAO,GACR,EAAE,WAAW,CAAC,QAAQ,CAAC,QAkCvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sitemap.d.ts","sourceRoot":"","sources":["../../src/views/Sitemap.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAkB9E,wBAAgB,aAAa,IAAI,4BAA4B,CAqB5D;AAED,wBAAgB,OAAO,gBA6BtB"}
1
+ {"version":3,"file":"Sitemap.d.ts","sourceRoot":"","sources":["../../src/views/Sitemap.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAkB9E,wBAAgB,aAAa,IAAI,4BAA4B,CAoB5D;AAED,wBAAgB,OAAO,gBA6BtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Splash.d.ts","sourceRoot":"","sources":["../../src/views/Splash.tsx"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,SAQ3B;yBARe,YAAY;;;;;;AAqC5B,eAAO,MAAM,8BAA8B,YAe1C,CAAC;AAEF,eAAO,MAAM,wBAAwB,YAOpC,CAAC"}
1
+ {"version":3,"file":"Splash.d.ts","sourceRoot":"","sources":["../../src/views/Splash.tsx"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,SAM3B;yBANe,YAAY;;;;;;AAmC5B,eAAO,MAAM,8BAA8B,YAe1C,CAAC;AAEF,eAAO,MAAM,wBAAwB,YAOpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Unmatched.d.ts","sourceRoot":"","sources":["../../src/views/Unmatched.tsx"],"names":[],"mappings":";AAwBA,2CAA2C;AAC3C,wBAAgB,SAAS,gBAoDxB"}
1
+ {"version":3,"file":"Unmatched.d.ts","sourceRoot":"","sources":["../../src/views/Unmatched.tsx"],"names":[],"mappings":";AAwBA,2CAA2C;AAC3C,wBAAgB,SAAS,gBA4CxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-router",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "main": "src/index.tsx",
5
5
  "types": "build/index.d.ts",
6
6
  "files": [
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "peerDependencies": {
63
63
  "@react-navigation/drawer": "^6.5.8",
64
- "expo": "^49.0.0-alpha.6",
64
+ "expo": "^49.0.0",
65
65
  "expo-constants": "*",
66
66
  "expo-linking": "*",
67
67
  "expo-status-bar": "*",
@@ -104,7 +104,7 @@
104
104
  },
105
105
  "dependencies": {
106
106
  "@bacons/react-views": "^1.1.3",
107
- "@expo/metro-runtime": "2.2.3",
107
+ "@expo/metro-runtime": "2.2.4",
108
108
  "@radix-ui/react-slot": "1.0.1",
109
109
  "@react-navigation/bottom-tabs": "~6.5.7",
110
110
  "@react-navigation/native": "~6.1.6",
package/src/ExpoRoot.tsx CHANGED
@@ -1,3 +1,4 @@
1
+ import Constants from "expo-constants";
1
2
  import { StatusBar } from "expo-status-bar";
2
3
  import React, { FunctionComponent, ReactNode, Fragment } from "react";
3
4
  import { Platform } from "react-native";
@@ -44,6 +45,11 @@ const INITIAL_METRICS = {
44
45
  insets: { top: 0, left: 0, right: 0, bottom: 0 },
45
46
  };
46
47
 
48
+ const hasViewControllerBasedStatusBarAppearance =
49
+ Platform.OS === "ios" &&
50
+ !!Constants.expoConfig?.ios?.infoPlist
51
+ ?.UIViewControllerBasedStatusBarAppearance;
52
+
47
53
  export function ExpoRoot({
48
54
  wrapper: ParentWrapper = Fragment,
49
55
  ...props
@@ -64,7 +70,9 @@ export function ExpoRoot({
64
70
  {children}
65
71
 
66
72
  {/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */}
67
- <StatusBar style="auto" />
73
+ {!hasViewControllerBasedStatusBarAppearance && (
74
+ <StatusBar style="auto" />
75
+ )}
68
76
  </SafeAreaProvider>
69
77
  </GestureHandlerRootView>
70
78
  </ParentWrapper>
@@ -90,7 +98,11 @@ function ContextNavigator({
90
98
  SplashScreen.hideAsync();
91
99
  if (process.env.NODE_ENV === "development") {
92
100
  const Tutorial = require("./onboard/Tutorial").Tutorial;
93
- return <Tutorial />;
101
+ return (
102
+ <WrapperComponent>
103
+ <Tutorial />
104
+ </WrapperComponent>
105
+ );
94
106
  } else {
95
107
  // Ensure tutorial styles are stripped in production.
96
108
  return null;
@@ -27,6 +27,7 @@ export class RouterStore {
27
27
  rootComponent!: ComponentType;
28
28
  linking: ExpoLinkingOptions | undefined;
29
29
  isReady: boolean = false;
30
+ private hasAttemptedToHideSplash: boolean = false;
30
31
 
31
32
  initialState: ResultState | undefined;
32
33
  rootState: ResultState | undefined;
@@ -118,8 +119,16 @@ export class RouterStore {
118
119
  (data) => {
119
120
  const state = data.data.state as ResultState;
120
121
 
121
- if (navigationRef.isReady()) {
122
- this.onReady();
122
+ if (!this.isReady) {
123
+ if (!this.hasAttemptedToHideSplash) {
124
+ this.hasAttemptedToHideSplash = true;
125
+ // NOTE(EvanBacon): `navigationRef.isReady` is sometimes not true when state is called initially.
126
+ requestAnimationFrame(() => _internal_maybeHideAsync());
127
+ }
128
+
129
+ if (navigationRef.isReady()) {
130
+ this.onReady();
131
+ }
123
132
  }
124
133
 
125
134
  let shouldUpdateSubscribers = this.nextState === state;
@@ -179,9 +188,6 @@ export class RouterStore {
179
188
 
180
189
  /** Make sure these are arrow functions so `this` is correctly bound */
181
190
  onReady = () => {
182
- if (!this.isReady) {
183
- requestAnimationFrame(() => _internal_maybeHideAsync());
184
- }
185
191
  this.isReady = true;
186
192
  };
187
193
  subscribeToRootState = (subscriber: () => void) => {
package/src/hooks.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  useStoreRouteInfo,
12
12
  } from "./global-state/router-store";
13
13
  import { Router } from "./types";
14
+ import { useDeprecated } from "./useDeprecated";
14
15
 
15
16
  type SearchParams = Record<string, string | string[]>;
16
17
 
@@ -28,19 +29,22 @@ export function useRootNavigation() {
28
29
 
29
30
  // Wraps useLinkTo to provide an API which is similar to the Link component.
30
31
  export function useLink() {
31
- console.warn("`useLink()` is deprecated in favor of `useRouter()`");
32
+ useDeprecated("`useLink()` is deprecated in favor of `useRouter()`");
32
33
  return useRouter();
33
34
  }
34
35
 
35
36
  export function useRouter(): Router {
36
- return {
37
- push: store.push,
38
- back: store.goBack,
39
- replace: store.replace,
40
- setParams: store.setParams,
41
- canGoBack: store.canGoBack,
42
- // TODO(EvanBacon): add `reload`
43
- };
37
+ return React.useMemo(
38
+ () => ({
39
+ push: store.push,
40
+ back: store.goBack,
41
+ replace: store.replace,
42
+ setParams: store.setParams,
43
+ canGoBack: store.canGoBack,
44
+ // TODO(EvanBacon): add `reload`
45
+ }),
46
+ []
47
+ );
44
48
  }
45
49
 
46
50
  /**
package/src/link/href.ts CHANGED
@@ -19,10 +19,8 @@ export const resolveHref = (href: Href): string => {
19
19
  const { pathname, params } = createQualifiedPathname(path, {
20
20
  ...href.params,
21
21
  });
22
- return (
23
- pathname +
24
- (Object.keys(params).length ? `?${createQueryParams(params)}` : "")
25
- );
22
+ const paramsString = createQueryParams(params);
23
+ return pathname + (paramsString ? `?${paramsString}` : "");
26
24
  };
27
25
 
28
26
  function createQualifiedPathname(
@@ -54,7 +52,11 @@ function encodeParam(param: any): string {
54
52
  }
55
53
 
56
54
  function createQueryParams(params: Record<string, any>): string {
57
- return Object.entries(params)
58
- .map(([key, value]) => `${key}=${encodeURIComponent(value.toString())}`)
59
- .join("&");
55
+ return (
56
+ Object.entries(params)
57
+ // Allow nullish params
58
+ .filter(([, value]) => value != null)
59
+ .map(([key, value]) => `${key}=${encodeURIComponent(value.toString())}`)
60
+ .join("&")
61
+ );
60
62
  }
@@ -11,8 +11,8 @@ function Header() {
11
11
  <Pressable>
12
12
  {({ hovered }) => (
13
13
  <Text
14
- accessibilityRole="header"
15
- accessibilityLevel={1}
14
+ role="heading"
15
+ aria-level={1}
16
16
  style={[styles.title, Platform.OS !== "web" && { textAlign: "left" }]}
17
17
  >
18
18
  Welcome to{" "}
@@ -62,11 +62,7 @@ export function Tutorial() {
62
62
  <SafeAreaView style={styles.safeArea}>
63
63
  <View style={styles.container}>
64
64
  <Header />
65
- <Text
66
- accessibilityRole="header"
67
- accessibilityLevel={2}
68
- style={styles.subtitle}
69
- >
65
+ <Text role="heading" aria-level={2} style={styles.subtitle}>
70
66
  Start by creating a file{"\n"}in the{" "}
71
67
  <Text style={{ fontWeight: "bold" }}>{getRootDir()}</Text>{" "}
72
68
  directory.
@@ -122,10 +118,7 @@ function Button() {
122
118
  },
123
119
  ]}
124
120
  >
125
- <Text
126
- selectable={false}
127
- style={[styles.code, hovered && { color: "black" }]}
128
- >
121
+ <Text style={[styles.code, hovered && { color: "black" }]}>
129
122
  <Text style={{ color: "#BCC3CD" }}>$</Text> touch {getRootDir()}
130
123
  /index.js
131
124
  </Text>
@@ -179,6 +172,7 @@ const styles = StyleSheet.create({
179
172
  color: "black",
180
173
  },
181
174
  code: {
175
+ userSelect: "none",
182
176
  fontSize: 18,
183
177
  transitionDuration: "200ms",
184
178
  fontWeight: "bold",
@@ -14,7 +14,7 @@ export function ScrollViewStyleReset() {
14
14
  <style
15
15
  id="expo-reset"
16
16
  dangerouslySetInnerHTML={{
17
- __html: `#root,body,html{height:100%}body{overflow:hidden}#root{display:flex}`,
17
+ __html: `#root,body{display:flex}#root,body,html{width:100%;-webkit-overflow-scrolling:touch;margin:0;padding:0;min-height:100%}#root{flex-shrink:0;flex-basis:auto;flex-grow:1;flex:1}html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;height:calc(100% + env(safe-area-inset-top))}body{overflow-y:auto;overscroll-behavior-y:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-ms-overflow-style:scrollbar}`,
18
18
  }}
19
19
  />
20
20
  );
@@ -0,0 +1,35 @@
1
+ import { useLayoutEffect } from "react";
2
+ import { Platform } from "react-native";
3
+
4
+ // Node environment may render in multiple processes causing the warning to log mutiple times
5
+ // Hence we skip the warning in these environments.
6
+ const canWarn = Platform.select({
7
+ native: process.env.NODE_ENV !== "production",
8
+ default:
9
+ process.env.NODE_ENV !== "production" && typeof window !== "undefined",
10
+ });
11
+
12
+ const warned = new Set<string>();
13
+
14
+ export function useWarnOnce(
15
+ message: string,
16
+ guard: unknown = true,
17
+ key = message
18
+ ) {
19
+ // useLayoutEffect typically doesn't run in node environments.
20
+ // Combined with skipWarn, this should prevent unwanted warnings
21
+ useLayoutEffect(() => {
22
+ if (guard && canWarn && !warned.has(key)) {
23
+ warned.add(key);
24
+ console.warn(message);
25
+ }
26
+ }, [guard]);
27
+ }
28
+
29
+ export function useDeprecated(
30
+ message: string,
31
+ guard: unknown = true,
32
+ key = message
33
+ ) {
34
+ return useWarnOnce(key, guard, `Expo Router: ${message}`);
35
+ }
@@ -62,11 +62,7 @@ export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) {
62
62
  alignItems: "center",
63
63
  }}
64
64
  >
65
- <Text
66
- accessibilityRole="header"
67
- accessibilityLevel={1}
68
- style={styles.title}
69
- >
65
+ <Text role="heading" aria-level={1} style={styles.title}>
70
66
  Something went wrong
71
67
  </Text>
72
68
  </View>
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
 
3
+ import { useDeprecated } from "../useDeprecated";
3
4
  import { useNavigation } from "../useNavigation";
4
5
 
5
6
  export type ScreenProps<
@@ -33,9 +34,24 @@ export function Screen<TOptions extends object = object>({
33
34
  const navigation = useNavigation(name);
34
35
 
35
36
  useLayoutEffect(() => {
36
- navigation.setOptions(options ?? {});
37
+ if (
38
+ options &&
39
+ // React Navigation will infinitely loop in some cases if an empty object is passed to setOptions.
40
+ // https://github.com/expo/router/issues/452
41
+ Object.keys(options).length
42
+ ) {
43
+ navigation.setOptions(options);
44
+ }
37
45
  }, [navigation, options]);
38
46
 
47
+ if (process.env.NODE_ENV === "development") {
48
+ // eslint-disable-next-line react-hooks/rules-of-hooks
49
+ useDeprecated(
50
+ "The `redirect` prop on <Screen /> is deprecated and will be removed. Please use `router.redirect` instead",
51
+ redirect
52
+ );
53
+ }
54
+
39
55
  if (process.env.NODE_ENV !== "production") {
40
56
  // eslint-disable-next-line react-hooks/rules-of-hooks
41
57
  React.useEffect(() => {
@@ -27,7 +27,6 @@ export function getNavOptions(): NativeStackNavigationOptions {
27
27
  headerTitleStyle: {
28
28
  color: "white",
29
29
  },
30
-
31
30
  headerTintColor: "white",
32
31
  headerLargeTitleStyle: {
33
32
  color: "white",
@@ -3,6 +3,8 @@ import { nanoid } from "nanoid/non-secure";
3
3
  import * as React from "react";
4
4
  import { Platform } from "react-native";
5
5
 
6
+ import { useDeprecated } from "../useDeprecated";
7
+
6
8
  const globalStack: string[] = [];
7
9
 
8
10
  /**
@@ -25,11 +27,9 @@ const globalStack: string[] = [];
25
27
  */
26
28
  export function SplashScreen() {
27
29
  useGlobalSplash();
28
- React.useEffect(() => {
29
- console.warn(
30
- "The <SplashScreen /> component is deprecated. Use `SplashScreen.preventAutoHideAsync()` and `SplashScreen.hideAsync` from `expo-router` instead."
31
- );
32
- }, []);
30
+ useDeprecated(
31
+ "The <SplashScreen /> component is deprecated. Use `SplashScreen.preventAutoHideAsync()` and `SplashScreen.hideAsync` from `expo-router` instead."
32
+ );
33
33
  return null;
34
34
  }
35
35
 
@@ -37,18 +37,10 @@ export function Unmatched() {
37
37
 
38
38
  return (
39
39
  <View style={styles.container}>
40
- <Text
41
- accessibilityRole="header"
42
- accessibilityLevel={1}
43
- style={styles.title}
44
- >
40
+ <Text role="heading" aria-level={1} style={styles.title}>
45
41
  Unmatched Route
46
42
  </Text>
47
- <Text
48
- accessibilityRole="header"
49
- accessibilityLevel={2}
50
- style={styles.subtitle}
51
- >
43
+ <Text role="heading" aria-level={2} style={styles.subtitle}>
52
44
  Page could not be found.{" "}
53
45
  <Text
54
46
  onPress={() => {
@@ -127,8 +127,6 @@ declare module "react-native" {
127
127
  /** @platform web */
128
128
  tabIndex?: number;
129
129
  /** @platform web */
130
- accessibilityLevel?: number;
131
- /** @platform web */
132
130
  lang?: string;
133
131
  }
134
132