Skip to content

Commit

Permalink
refactor: add eslint-plugin-react-hooks (#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcalexiei authored Dec 22, 2024
1 parent d09ca55 commit 986de49
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 302 deletions.
15 changes: 15 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import eslint from '@eslint/js'
import tseslint from 'typescript-eslint'
// @ts-expect-error no types are available for this plugin
import eslintPluginImport from 'eslint-plugin-import'
// @ts-expect-error no types are available for this plugin
import eslintPluginReactHooks from 'eslint-plugin-react-hooks'

export default tseslint.config(
{
Expand Down Expand Up @@ -139,6 +141,19 @@ export default tseslint.config(
// #endregion misc
},
},

{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
plugins: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
'react-hooks': eslintPluginReactHooks,
},
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error',
},
},

{
files: ['apps/documentation/**'],
settings: {
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
"eslint": "^9.15.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-hooks": "5.1.0",
"prettier": "^3.2.4",
"turbo": "^2.2.3",
"typescript": "5.6.3",
Expand Down
15 changes: 2 additions & 13 deletions packages/router/src/components/RouteMatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const RouteMatch = ({
}: RouteMatchProps): React.JSX.Element => {
const { data, isLoading } = useServerSideProps(route, serverSideProps)

// eslint-disable-next-line react-hooks/exhaustive-deps
const routes = React.useMemo(() => loadParentComponents(route), [route.id])

return (
Expand All @@ -29,12 +30,6 @@ export const RouteMatch = ({
)
}

interface ParentProps<TData = unknown> {
children: React.ReactNode
data: TData
isLoading: boolean
}

interface TraverseRootComponentsProps<TData = unknown> {
routes: Array<Route>
data: TData
Expand All @@ -58,13 +53,7 @@ const TraverseRootComponents = React.memo(
children,
}: TraverseRootComponentsProps): React.JSX.Element => {
if (routes.length > index) {
const Parent = React.useMemo(
() =>
routes[index]?.component as unknown as (
props: ParentProps,
) => React.JSX.Element,
[],
)
const Parent = (routes[index] as Route).component

return (
<Parent data={data} isLoading={isLoading}>
Expand Down
4 changes: 2 additions & 2 deletions packages/router/src/components/RouterProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import type { ReactNode, JSX } from 'react'

import { useListenBrowserUrlUpdates } from '../hooks/useListenBrowserUrlUpdates'
import { initRouterStore } from '../hooks/useRouterStore'
import { useInitRouterStore } from '../hooks/useRouterStore'
import type { ServerProps } from '../types'
import type { Router } from '../router'

Expand Down Expand Up @@ -39,7 +39,7 @@ export function RouterProvider({
router,
serverProps,
}: RouterProviderProps): JSX.Element {
initRouterStore(serverProps)
useInitRouterStore(serverProps)

useListenBrowserUrlUpdates()

Expand Down
27 changes: 15 additions & 12 deletions packages/router/src/hooks/useListenBrowserUrlUpdates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,26 @@ import { useRouterStore } from './useRouterStore'
export const useListenBrowserUrlUpdates = (): void => {
const updateLocation = useRouterStore((st) => st.updateLocation)

const updateLocationOnPopStateChange = ({ target }: PopStateEvent): void => {
const { pathname, hash, href, search } = (target as typeof window).location
useEffect(() => {
const updateLocationOnPopStateChange = ({
target,
}: PopStateEvent): void => {
const { location } = target as typeof window
const { pathname, hash, href, search } = location

updateLocation({
pathname,
hash,
href,
searchStr: search,
search: Object.fromEntries(new URLSearchParams(search)),
})
}
updateLocation({
pathname,
hash,
href,
searchStr: search,
search: Object.fromEntries(new URLSearchParams(search)),
})
}

useEffect(() => {
window.addEventListener('popstate', updateLocationOnPopStateChange)

return (): void => {
window.removeEventListener('popstate', updateLocationOnPopStateChange)
}
}, [])
}, [updateLocation])
}
4 changes: 2 additions & 2 deletions packages/router/src/hooks/useRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ export function sanitizePathname(pathname: string): string {
* Optimizations should occour on both
*/
export default function useRoute(pathname?: string): Route | undefined {
const { routesById } = useInternalRouter()

if (!pathname) return

pathname = sanitizePathname(pathname)

const { routesById } = useInternalRouter()

if (routesById[pathname]) return routesById[pathname]

const dynamicRoutes = Object.keys(routesById).filter((route) =>
Expand Down
4 changes: 2 additions & 2 deletions packages/router/src/hooks/useRouterStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface RouterState {
updateLocation: (loc: ParsedLocation) => void
}

export const initRouterStore = (props?: ServerProps): void => {
export const useInitRouterStore = (props?: ServerProps): void => {
const updateLocation = useRouterStore((st) => st.updateLocation)

// Init the store in the server in order to correctly
Expand All @@ -49,7 +49,7 @@ export const initRouterStore = (props?: ServerProps): void => {
searchStr: search,
search: Object.fromEntries(new URLSearchParams(search)),
})
}, [])
}, [updateLocation])
}

export const useRouterStore = create<RouterState>()((set) => ({
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/hooks/useServerSideProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function useServerSideProps<T>(
return (): void => {
setData(undefined)
}
}, [location.pathname])
}, [location.pathname, route.options.hasHandler, updateLocation])

return { isLoading, data: data as T }
}
4 changes: 3 additions & 1 deletion packages/router/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ComponentType as ReactComponentType } from 'react'
import type { ComponentType as ReactComponentType, ReactNode } from 'react'

export interface Segment {
type: 'pathname' | 'param' | 'wildcard'
Expand All @@ -17,6 +17,8 @@ export interface ServerProps<TProps = unknown> {
export interface RouteProps<TData = unknown> {
data: TData
isLoading: boolean

children?: ReactNode
}

export type RouteComponent = ReactComponentType<RouteProps> & {
Expand Down
Loading

0 comments on commit 986de49

Please sign in to comment.