Skip to content

Commit

Permalink
adds eslint and fix some hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
natew committed May 9, 2024
1 parent cdd288c commit 85c4989
Show file tree
Hide file tree
Showing 20 changed files with 740 additions and 68 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
**/*/types
14 changes: 14 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"plugin:react-hooks/recommended"
],
"rules": {
"@typescript-eslint/consistent-type-imports": ["error", {
"prefer": "type-imports",
"fixStyle": "separate-type-imports",
"disallowTypeAnnotations": false
}]
}
}
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "vite-react-native-monorepo",
"name": "vxrn-monorepo",
"private": true,
"version": "0.0.0",
"repository": {
Expand All @@ -26,8 +26,9 @@
"clean:ts": "tsc -b --clean tsconfig.json",
"clean": "yarn turbo:run clean:build",
"fix": "manypkg fix",
"lint:fix": "ultra -r --no-pretty lint:fix",
"lint": "ultra -r --no-pretty lint",
"lint:fix": "yarn lint:eslint --fix && ultra -r --no-pretty lint:fix",
"lint": "yarn lint:eslint && ultra -r --no-pretty lint",
"lint:eslint": "echo eslint && eslint '**/*.{ts,tsx}'",
"dev:example-tamagui": "yarn workspace example-tamagui dev",
"dev:example-router": "rm -r examples/router/node_modules/.vite || true && yarn workspace example-router dev",
"dev:example-bare": "yarn workspace example-bare dev",
Expand All @@ -41,10 +42,15 @@
"dependencies": {
"@biomejs/biome": "^1.6.3",
"@manypkg/cli": "^0.19.1",
"@types/eslint": "^8",
"@types/react": "^18.2.24",
"@types/react-native": "~0.70.6",
"@typescript-eslint/eslint-plugin": "^6.19.1",
"@typescript-eslint/parser": "^6.19.1",
"check-dependency-version-consistency": "^3.0.3",
"esbuild-register": "^3.5.0",
"eslint": "^8.56.0",
"eslint-plugin-react-hooks": "^4.6.2",
"npm-run-all": "^4.1.5",
"p-map": "^5.5.0",
"patch-package": "^8.0.0",
Expand Down
22 changes: 20 additions & 2 deletions packages/router/src/LocationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,28 @@ export function getRouteInfoFromState(
}
}

type RouteLikeTree = { name: string; state?: { routes?: RouteLikeTree[] } }

function getActualLastRoute<A extends RouteLikeTree>(routeLike: A): A {
// if group, traverse
if (routeLike.name[0] === '(' && routeLike.state?.routes) {
const routes = routeLike.state.routes
return getActualLastRoute(routes[routes.length - 1]) as any
}
return routeLike
}

function isIndexPath(state: State) {
const route = state.routes[state.index ?? state.routes.length - 1]
const route = getActualLastRoute(state.routes[state.index ?? state.routes.length - 1])

if (route.state) {
return isIndexPath(route.state)
}

if (route.name === 'index') {
return true
}

// Index routes on the same level as a layout do not have `index` in their name
if (route.params && 'screen' in route.params) {
return route.params.screen === 'index'
Expand All @@ -43,7 +59,9 @@ function isIndexPath(state: State) {
// So we need to do a positive lookahead to check if the route ends with /index
// Nested routes that are hoisted will have a name ending with /index
// e.g name could be /user/[id]/index
if (route.name.match(/.+\/index$/)) return true
if (route.name.match(/.+\/index$/)) {
return true
}

// The state will either have params (because there are multiple _layout) or it will be hoisted with a name
// If we don't match the above cases, then it's not an index route
Expand Down
21 changes: 14 additions & 7 deletions packages/router/src/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { StrictMode } from 'react'
import { ExpoRoot, type ExpoRootProps } from './ExpoRoot'
import { RootErrorBoundary } from './RootErrorBoundary'
import type { GlobbedRouteImports } from './types'
Expand All @@ -19,13 +20,19 @@ export function Root({ routes, path, ...props }: RootProps) {
const context = useViteRoutes(routes, globalThis['__vxrnVersion'])

return (
<RootErrorBoundary>
<ExpoRoot
location={path ? new URL(`http://localhost:3333${path}`) : undefined}
context={context}
{...props}
/>
</RootErrorBoundary>
<StrictMode>
<RootErrorBoundary>
<ExpoRoot
location={
typeof window !== 'undefined'
? new URL(path || window.location.pathname || '/', window.location.href)
: new URL(path || '/', 'https://localhost')
}
context={context}
{...props}
/>
</RootErrorBoundary>
</StrictMode>
)
}

Expand Down
1 change: 1 addition & 0 deletions packages/router/src/fork/useLinking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export default function useLinking(
}

const thenable = {
// biome-ignore lint/suspicious/noThenProperty: <explanation>
then(onfulfilled?: (state: ResultState | undefined) => void) {
return Promise.resolve(onfulfilled ? onfulfilled(value) : value)
},
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/getLinkingConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function getLinkingConfig(routes: RouteNode, metaOnly = true): ExpoLinkin
return (
getPathFromState(state, {
screens: [],
...this.config,
// ...this.config,
...options,
}) ?? '/'
)
Expand Down
4 changes: 2 additions & 2 deletions packages/router/src/getServerManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function uniqueBy<T>(arr: T[], key: (item: T) => string): T[] {
export function getServerManifest(route: RouteNode): ExpoRouterServerManifestV1 {
function getFlatNodes(route: RouteNode): [string, RouteNode][] {
if (route.children.length) {
return route.children.map((child) => getFlatNodes(child)).flat()
return route.children.flatMap((child) => getFlatNodes(child))
}

// API Routes are handled differently to HTML routes because they have no nested behavior.
Expand Down Expand Up @@ -193,7 +193,7 @@ function getNamedParametrizedRoute(route: string) {
if (cleanedKey.length === 0 || cleanedKey.length > 30) {
invalidKey = true
}
if (!isNaN(parseInt(cleanedKey.slice(0, 1), 10))) {
if (!Number.isNaN(Number.parseInt(cleanedKey.slice(0, 1), 10))) {
invalidKey = true
}

Expand Down
6 changes: 3 additions & 3 deletions packages/router/src/head/ExpoHead.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function useActivityFromMetaChildren(meta: MetaNode[]) {

cachedActivity.current = userActivity
return userActivity
}, [meta, pathname, href])
}, [sortedMeta])

const parsedActivity: UserActivity = {
keywords: [title],
Expand Down Expand Up @@ -205,7 +205,7 @@ function useRegisterCurrentActivity(activity: UserActivity) {
// Using all segments ensures that cascading routes are considered.
const activityId = urlToId(usePathname() || '/')
const cascadingId = urlToId(useSegments().join('-') || '-')
const activityIds = Array.from(activities.keys())

const cascadingActivity: UserActivity = React.useMemo(() => {
// Get all nested activities together, then update the id to match the current pathname.
// This enables cases like `/user/[name]/post/[id]` to match all nesting, while still having a URL-specific ID, i.e. `/user/evanbacon/post/123`
Expand All @@ -222,7 +222,7 @@ function useRegisterCurrentActivity(activity: UserActivity) {
activities.set(cascadingId, cascadingActivity)

return cascadingActivity
}, [cascadingId, activityId, activity, activityIds])
}, [cascadingId, activityId, activity])

const previousActivity = React.useRef<UserActivity | null>(null)

Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/layouts/withLayoutContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function useFilterScreenChildren(
screens,
children: customChildren,
}
}, [children])
}, [children, contextKey, isCustomNavigator])
}

/** Return a navigator that automatically injects matched routes and renders nothing when there are no children. Return type with children prop optional */
Expand Down
6 changes: 3 additions & 3 deletions packages/router/src/link/useLoadedNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function useLoadedNavigation() {
if (navigationRef.current) {
flush()
}
}, [flush])
}, [flush, navigationRef])

const push = useCallback(
(fn: (navigation: GenericNavigation) => void) => {
Expand All @@ -44,7 +44,7 @@ export function useLoadedNavigation() {
flush()
}
},
[flush]
[flush, navigationRef]
)

return push
Expand All @@ -56,7 +56,7 @@ export function useOptionalNavigation(): GenericNavigation | null {

useEffect(() => {
loadNavigation((nav) => setNavigation(nav))
}, [])
}, [loadNavigation])

return navigation
}
24 changes: 20 additions & 4 deletions packages/router/src/render.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
import { startTransition } from 'react'
import { hydrateRoot } from 'react-dom/client'
import { loadRoutes } from './useViteRoutes'

globalThis['__vxrnVersion'] ||= 0

export function render(App: (props: { path: string }) => JSX.Element, rootQuerySelector = '#root') {
export function render(
App: (props: { path: string }) => JSX.Element,
routes?: any,
rootQuerySelector = '#root'
) {
if (typeof document === 'undefined') return
const container = document.querySelector(rootQuerySelector)
if (!container) throw new Error(`No container element found`)
const element = <App path={window.location.pathname} />
if (globalThis['__vxrnRoot']) {
globalThis['__vxrnVersion']++
globalThis['__vxrnRoot'].render(element)
} else {
startTransition(() => {
function flush() {
if (!container) {
throw new Error(`No container element found`)
}
// startTransition(() => {
globalThis['__vxrnRoot'] = hydrateRoot(container, element)
})
// })
}

if (routes) {
// loadRoutes(routes)
flush()
} else {
flush()
}
}
}
2 changes: 1 addition & 1 deletion packages/router/src/useDeprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function useWarnOnce(message: string, guard: unknown = true, key = messag
warned.add(key)
console.warn(message)
}
}, [guard])
}, [guard, key, message])
}

export function useDeprecated(message: string, guard: unknown = true, key = message) {
Expand Down
3 changes: 2 additions & 1 deletion packages/router/src/useLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export function useLoader<
>(loader: Loader): Returned extends Promise<any> ? Awaited<Returned> : Returned {
const initialData = useRef(globalThis['__vxrnLoaderData__'])
return typeof loader === 'function'
? useAsyncFn(loader, globalThis['__vxrnLoaderProps__'])
? // eslint-disable-next-line react-hooks/rules-of-hooks
useAsyncFn(loader, globalThis['__vxrnLoaderProps__'])
: initialData.current
}

Expand Down
15 changes: 6 additions & 9 deletions packages/router/src/useScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ function getSortedChildren(
...entries.sort(sortRoutesWithInitial(initialRouteName)).map((route) => ({ route, props: {} }))
)

console.log('sorted', ordered)

return ordered
}

Expand All @@ -110,14 +108,13 @@ function getSortedChildren(
export function useSortedScreens(order: ScreenProps[]): React.ReactNode[] {
const node = useRouteNode()

const sorted = node?.children?.length
? getSortedChildren(node.children, order, node.initialRouteName)
: []
return React.useMemo(() => {
const sorted = node?.children?.length
? getSortedChildren(node.children, order, node.initialRouteName)
: []

return React.useMemo(
() => sorted.map((value) => routeToScreen(value.route, value.props)),
[sorted]
)
return sorted.map((value) => routeToScreen(value.route, value.props))
}, [node?.children, node?.initialRouteName, order])
}

function fromImport({ ErrorBoundary, ...component }: LoadedRoute) {
Expand Down
4 changes: 4 additions & 0 deletions packages/router/src/useViteRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export function loadRoutes(paths: any) {
})
}

// this is called in useScreens value.loadRoute
// see getRoutes.ts contextModule.loadRoute
// where contextModule === this resolve function
console.info(`loadRoute`, id)
throw promises[id]
}

Expand Down
1 change: 0 additions & 1 deletion packages/router/src/views/Try.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export class Try extends React.Component<
}

render() {
console.log('asdsadasdsa')
const { error } = this.state
const { catch: ErrorBoundary, children } = this.props
if (!error) {
Expand Down
3 changes: 3 additions & 0 deletions packages/router/src/vite/createFileSystemRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export function createFileSystemRouter(options: Options): Plugin {
// }
const routeFile = join(root, route.file)

// warm up the entry
void server.warmupRequest(routeFile)

try {
const exported = await server.ssrLoadModule(routeFile, {
fixStacktrace: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/router/types/render.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// <reference types="react" />
export declare function render(App: (props: {
path: string;
}) => JSX.Element, rootQuerySelector?: string): void;
}) => JSX.Element, routes?: any, rootQuerySelector?: string): void;
//# sourceMappingURL=render.d.ts.map
Loading

0 comments on commit 85c4989

Please sign in to comment.