Skip to content

Feature/react location #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
`git clone https://github.com/nejcrogelsek/react-project-template.git`
2. Delete .git file inside cloned project.
3. Run: `yarn run start:clean`
4. Run: `yarn run husky:postinstall` to install husky git hook (automatically formats the code when pushing code to github)
4. Initialize git & run: `yarn run husky:postinstall` to install husky git hook (automatically formats the code when pushing code to github)

**With react-location instead of react-router-dom:**
1. Clone project by running:
`git clone https://github.com/nejcrogelsek/react-project-template.git`
2. Fetch the react-location branch:
`git fetch origin feature/react-location`
3. Checkout into react-location branch:
`git checkout feature/react-location`
4. Delete .git file inside project.
5. Run: `yarn run start:clean`
6. Initialize git & run: `yarn run husky:postinstall` to install husky git hook (automatically formats the code when pushing code to github)

## Available Scripts

Expand Down
10 changes: 4 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"eject": "react-scripts eject",
"start:clean": "rm -rf node_modules/ && rm -rf yarn.lock && rm -rf yarn-error.log && yarn && yarn start",
"generate:icons": "node scripts/generate-icons.js",
"generate:images": "node scripts/generate-images.js",
"generate:component": "npx generate-react-cli component",
"generate:page": "npx generate-react-cli component --type=page",
"update:check": "yarn outdated",
Expand All @@ -19,12 +18,13 @@
"code:check": "prettier --check \"src/**/*.{ts,tsx,js,css,scss,html}\"",
"code:format": "prettier --write \"src/**/*.{ts,tsx,js,css,scss,html}\"",
"code:format:specific-file": "prettier --write",
"lint": "eslint .",
"lint:fix": "eslint --fix ."
"lint": "eslint .",
"lint:fix": "eslint --fix ."
},
"dependencies": {
"@hookform/resolvers": "^2.8.8",
"@material-ui/core": "^4.12.4",
"@tanstack/react-location": "^3.7.4",
"@tanstack/react-location-devtools": "^3.4.4",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^8.0.0",
Expand All @@ -42,7 +42,6 @@
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-hook-form": "^7.29.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"styled-components": "^5.3.5",
"typescript": "^4.6.3",
Expand All @@ -51,7 +50,6 @@
},
"devDependencies": {
"@types/classnames": "^2.3.1",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.25",
"@types/yup": "^0.29.13",
"@typescript-eslint/eslint-plugin": "^5.18.0",
Expand Down
11 changes: 7 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { FC } from 'react'
import { Router, Outlet } from '@tanstack/react-location'
import { ReactLocationDevtools } from '@tanstack/react-location-devtools'

//Partials
import Header from './components/partials/Header/Header'
import Footer from './components/partials/Footer/Footer'
import Routes from './routes/Routes'
import { routes, location } from './routes/Routes'

const App: FC = () => {
return (
<>
<Router routes={routes} location={location}>
<Header />
<Routes />
<Outlet />
<Footer />
</>
<ReactLocationDevtools />
</Router>
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/ConfirmationModal/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const ConfirmationModal: FC<Props> = ({ confirmationData }: Props) => {

useEffect(() => {
cancel()
}, [router.location.pathname])
}, [router.location.current.pathname])

const confirm = () => {
if (confirmationData.onConfirm) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/partials/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FC } from 'react'
import { Link } from 'react-router-dom'
import { Link } from '@tanstack/react-location'

const Header: FC = () => {
return (
Expand Down
5 changes: 1 addition & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createRoot } from 'react-dom/client'
import { BrowserRouter as Router } from 'react-router-dom'
import { ThemeProvider } from 'styled-components'
import theme from 'styles/shared/theme'
import GlobalStyle from 'styles/shared/global'
Expand All @@ -12,9 +11,7 @@ const root = createRoot(container)
root.render(
<ThemeProvider theme={theme}>
<GlobalStyle />
<Router>
<App />
</Router>
<App />
</ThemeProvider>,
)

Expand Down
14 changes: 7 additions & 7 deletions src/lib/hooks/useQueryParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ const mergeValues = (
}
export function useQueryParameters(): QueryParameters {
const router = useRouter()
const values = qs.parse(router.location.search, qsOptions)
const hash = router.location.hash.length > 1 ? router.location.hash : undefined
const values = qs.parse(router.location.current.search.toString(), qsOptions)
const hash = router.location.current.hash.length > 1 ? router.location.current.hash : undefined
const getUrlWithQueryParams = (fields: string | { [field: string]: FilterValue }, value?: FilterValue) => {
const newValues = mergeValues(values, fields, value)
const queryString = qs.stringify(newValues, qsOptions)
const url = `${router.location.pathname}?${queryString}${hash || ''}`
const url = `${router.location.current.pathname}?${queryString}${hash || ''}`
return url
}
const set: QueryParameters['set'] = (fields: string | { [field: string]: FilterValue }, value?: FilterValue) => {
const url = getUrlWithQueryParams(fields, value)
router.navigate(url, { replace: true })
router.navigate({ to: url, replace: true })
}
function get(name: string): string | undefined {
const val = values[name]
Expand Down Expand Up @@ -102,11 +102,11 @@ export function useQueryParameters(): QueryParameters {
}
function setHash(value: string | undefined) {
const suffix = value ? `#${value}` : ''
const url = `${router.location.pathname}${router.location.search}${suffix}`
router.navigate(url, { replace: true })
const url = `${router.location.current.pathname}${router.location.current.search}${suffix}`
router.navigate({ to: url, replace: true })
}
return {
path: router.location.pathname,
path: router.location.current.pathname,
hash,
getNumber,
get,
Expand Down
4 changes: 1 addition & 3 deletions src/lib/hooks/useRouter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { useNavigate, useLocation, useParams } from 'react-router-dom'
import { useNavigate, useLocation } from '@tanstack/react-location'

export function useRouter() {
const navigate = useNavigate()
const location = useLocation()
const params = useParams()

return {
navigate,
location,
params,
}
}
2 changes: 1 addition & 1 deletion src/lib/hooks/useScrollToTop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export const useScrollToTop = () => {
const router = useRouter()
useEffect(() => {
window.scrollTo(0, 0)
}, [router.location.pathname])
}, [router.location.current.pathname])
}
3 changes: 2 additions & 1 deletion src/pages/ForgotPassword/ForgotPassword.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FC } from 'react'
import isRestricted from 'routes/isRestricted'

interface Props {}

Expand All @@ -10,4 +11,4 @@ const ForgotPassword: FC<Props> = (props: Props) => {
)
}

export default ForgotPassword
export default isRestricted(ForgotPassword)
4 changes: 2 additions & 2 deletions src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { FC } from 'react'
import { NavLink } from 'react-router-dom'
import { Link } from '@tanstack/react-location'
import Icon from 'components/shared/Icon/Icon'

const Home: FC = () => {
return (
<div className="home">
<h1>Home component</h1>
<NavLink to="/login"> Go to Login</NavLink>
<Link to="/login"> Go to Login</Link>

<Icon icon="close" />
<Icon icon="logo" />
Expand Down
4 changes: 3 additions & 1 deletion src/pages/Login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { FC } from 'react'
import isRestricted from 'routes/isRestricted'

import LoginForm from 'components/user/LoginForm/LoginForm'

interface Props {}
Expand All @@ -11,4 +13,4 @@ const Login: FC<Props> = (props: Props) => {
)
}

export default Login
export default isRestricted(Login)
3 changes: 2 additions & 1 deletion src/pages/Profile/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FC } from 'react'
import isPrivate from 'routes/isPrivate'

interface Props {}

Expand All @@ -10,4 +11,4 @@ const Profile: FC<Props> = (props: Props) => {
)
}

export default Profile
export default isPrivate(Profile)
4 changes: 3 additions & 1 deletion src/pages/Register/Register.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { FC } from 'react'
import isRestricted from 'routes/isRestricted'

import RegisterForm from 'components/user/RegisterForm/RegisterForm'

interface Props {}
Expand All @@ -11,4 +13,4 @@ const Register: FC<Props> = (props: Props) => {
)
}

export default Register
export default isRestricted(Register)
3 changes: 2 additions & 1 deletion src/pages/ResetPassword/ResetPassword.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FC } from 'react'
import isRestricted from 'routes/isRestricted'

interface Props {}

Expand All @@ -10,4 +11,4 @@ const ResetPassword: FC<Props> = (props: Props) => {
)
}

export default ResetPassword
export default isRestricted(ResetPassword)
16 changes: 0 additions & 16 deletions src/routes/PrivateRoute.tsx

This file was deleted.

13 changes: 0 additions & 13 deletions src/routes/RestrictedRoute.tsx

This file was deleted.

64 changes: 15 additions & 49 deletions src/routes/Routes.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { FC } from 'react'
import { RouteProps, Routes as Switch, Route } from 'react-router-dom'

import PrivateRoute from './PrivateRoute'
import RestrictedRoute from './RestrictedRoute'
import { ReactLocation, Route } from '@tanstack/react-location'

import ForgotPassword from 'pages/ForgotPassword/ForgotPassword'
import Home from 'pages/Home/Home'
Expand All @@ -12,69 +8,39 @@ import Profile from 'pages/Profile/Profile'
import Register from 'pages/Register/Register'
import ResetPassword from 'pages/ResetPassword/ResetPassword'

export enum RouteType {
PUBLIC,
PRIVATE,
RESTRICTED,
}
interface AppRoute extends RouteProps {
type?: RouteType
}
export const AppRoutes: AppRoute[] = [
export const location = new ReactLocation()

export const routes: Route[] = [
// Restricted Routes
{
type: RouteType.RESTRICTED,
path: 'login',
children: <Login />,
element: <Login />,
},
{
type: RouteType.RESTRICTED,
path: 'register',
children: <Register />,
element: <Register />,
},
{
type: RouteType.RESTRICTED,
path: 'forgot-password',
children: <ForgotPassword />,
element: <ForgotPassword />,
},
{
type: RouteType.RESTRICTED,
path: 'reset-password',
children: <ResetPassword />,
element: <ResetPassword />,
},
// Private Routes
{
type: RouteType.PRIVATE,
path: 'my-profile',
children: <Profile />,
element: <Profile />,
},
// Public Routes
{
type: RouteType.PUBLIC,
path: '/',
children: <Home />,
element: <Home />,
},
// 404 Error
{
path: '*',
element: <Page404 />,
},
]

const Routes: FC = () => {
return (
<Switch>
{AppRoutes.map((r) => {
const { type } = r
if (type === RouteType.PRIVATE) {
return <Route key={`${r.path}`} path={`/${r.path}`} element={<PrivateRoute>{r.children}</PrivateRoute>} />
}
if (type === RouteType.RESTRICTED) {
return (
<Route key={`${r.path}`} path={`/${r.path}`} element={<RestrictedRoute>{r.children}</RestrictedRoute>} />
)
}

return <Route key={`${r.path}`} path={`/${r.path}`} element={r.children} />
})}
<Route path="*" element={<Page404 />} />
</Switch>
)
}

export default Routes
17 changes: 17 additions & 0 deletions src/routes/isPrivate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FC } from 'react'
import { Navigate } from '@tanstack/react-location'
import authStore from 'lib/stores/auth.store'

const isPrivate = (OriginalComponent: FC) => {
const EnhancedComponent: FC = () => {
return authStore.isAuthenticated ? (
<OriginalComponent />
) : (
<Navigate to={`/login?redirect=${encodeURIComponent(location.pathname)}`} />
)
}

return EnhancedComponent
}

export default isPrivate
Loading