Exactly one route not working after deployed on Netlify - javascript

I have a react app in which i open a new tab to view products using a window.open(). This is working perfectly fine when i am working locally but after i deployed it to netlify that particular route says Page Not Found Error.
Below is my App.js
import React, { Suspense, lazy } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
// for components
import AdminProtectRoute from "./components/AdminProtectRoute";
import UserProtectRoute from "./components/UserProtectRoute";
import Spinner from "./components/Spinner";
// for user
const BookDetails = lazy(() => import("./components/user/BookDetails"));
const UserInventory = lazy(() => import("./components/user/UserInventory"));
const UserIssuedBooks = lazy(() => import("./components/user/UserIssuedBooks"));
const UserRequested = lazy(() => import("./components/user/UserRequested"));
const ForgotLink = lazy(() => import("./components/user/ForgotLink"));
const ForgotPass = lazy(() => import("./components/user/ForgotPass"));
const Contact = lazy(() => import("./components/user/Contact"));
const WishList = lazy(() => import("./components/user/WishList"));
const MyAccount = lazy(() => import("./components/user/MyAccount"));
const EditProfile = lazy(() => import("./components/user/EditProfile"));
function App() {
return (
<div className="app">
<ToastContainer />
<Router>
<Suspense fallback={<Spinner />}>
<Routes>
<Route element={<UserProtectRoute />}>
<Route path="/users" element={<User />}>
<Route index path="userissued" element={<UserIssuedBooks />} />
<Route path="userrequested" element={<UserRequested />} />
<Route path="userinventory" element={<UserInventory />} />
<Route path=":bookId" element={<BookDetails />} /> // this route is not working
<Route path="wishlist" element={<WishList />} />
</Route>
<Route path="/account" element={<MyAccount />} />
<Route path="/edit-profile" element={<EditProfile />} />
</Route>
</Routes>
</Suspense>
</Router>
</div>
);
}
export default App;
Below i my handler function in one of my components which is triggered by a button click that creates a new tab for that :bookId route:
const handleView = () => {
window.open('http://localhost:3000/users/' + book._id, "_blank")
}
When i replace http://localhost:3000 with https://my_app.netlify.app and deploy it, this function creates a new tab but gives me "Page not Found" Error but locally it creates a new tab and renders the required component as well.
Also i tried to enter the :bookId in my same tabs url search bar like given below:
https://my_app.netlify.app/users/63cb6d482ef3b2
but even this is not working
I tried my solve this but i unable to do so. Please help. Thanks in advance.

You have to setup the redirects, create a netlify.toml in the root of your project, and add something like:
[[redirects]]
from = "/*"
to = "/"
status = 200
Check : https://docs.netlify.com/configure-builds/file-based-configuration/#redirects

Related

Navigate in different Routes React

I have an authentication system, and I want to show different <Routes> with different available paths considering from login state.
I uesd <Navigate/> element for redirection from hidden pages depending login state. But there is a problem. <Navigate/> redirects without considering the state.
For example, when I logged in and try to open Login page I must redirects to a Main page, and when I don't logged in and try to open profile I must redirect to Login Page. And when I try to open any of this pages I automaticly redirects to Main page.
routes.jsx:
import React from 'react';
import {
Routes,
Route,
Navigate
} from 'react-router-dom';
import Profile from './pages/Profile/Main/Profile';
import Login from './pages/Auth/Login/Login';
import Register from './pages/Auth/Register/Register';
import Main from './pages/Main/Main';
import { Loans } from './pages/Profile/Active/Loans';
import ErrorPage from './pages/errorPage/ErrorPage';
export const useRoutes = isAuthenticated => {
if(isAuthenticated){
return (
<Routes>
<Route path='/profile' exact>
<Route index path=":id" element={<Profile/>}/>
<Route path="loans" element={<Loans/>} exact/>
</Route>
<Route path='/' exact element={<Main/>}/>
<Route
path="*"
element={<ErrorPage/>}
/>
<Route
path="/auth/*"
element={<Navigate to="/" replace />}
/>
</Routes>
);
} else {
return (
<Routes>
<Route path='/auth' exact>
<Route path='login' element={<Login/>} exact />
<Route path="register" exact element={<Register/>}/>
<Route
path=""
element = {
<Navigate to="login" replace />
}
/>
</Route>
<Route path='/' exact element={<Main/>}/>
<Route
path="/profile/*"
element={<Navigate to="/auth/login" replace />}
/>
<Route
path="*"
element={<ErrorPage/>}
/>
</Routes>
)
}
}
App.jsx:
import {
BrowserRouter
} from 'react-router-dom';
import {useRoutes} from './routes';
import 'materialize-css';
import { useAuth } from './hooks/auth.hook';
import { AuthContext } from './context/auth.context';
function App() {
const {token, userId, login, logout} = useAuth();
const isAuthenticated = !!token;
const routes = useRoutes(isAuthenticated);
return (
<AuthContext.Provider value = {{
token, login, logout, userId, isAuthenticated
}}>
<BrowserRouter>
<div className="container">
{routes}
</div>
</BrowserRouter>
</AuthContext.Provider>
);
}
export default App;
One issue that may be causing this is you check authentication based on whether the token exists. Debug the output of that variable to see if it is cleared correctly when you log out. Next, you are determining authentication once inside of App(), fetching the routes from useRoutes(), and then rendering the app without ever checking again if the authentication is still valid. A better approach would be something like this:
const auth = useAuth();
return ({auth.isAuthenticated ? (
<Fragment>
<Link to="/account">Account ({auth.user.email})</Link>
<Button onClick={() => auth.signout()}>Signout</Button>
</Fragment>
) : (
<Link to="/signin">Signin</Link>
)});

how to redirect in react v6

I need to navigate back to the original requested URL after login.
For example, the user enters www.eCart.com/Cart as the user is not authenticated, it will navigate to the login page www.eCart.com/login.
Once authenticated, it should navigate back to www.eCart.com/Cart automatically
my protectedRoute.js looks like this
import React from 'react'
import { connect } from 'react-redux'
import { Navigate, Outlet, useLocation, useNavigate} from 'react-router-dom'
export const withRouter = (Component) => { //works only for react16-17 //hooks
const Wrapper = (props) => {
const location = useLocation()
const navigate = useNavigate();
return (
<Component
navigate = {navigate}
{...props}
location={location}
{...props}
/>
);
};
return Wrapper;
};
const ProtectedRoute = ({component:Component, auth,...rest}) => (
auth.isAuthenticated ? <Outlet /> : <Navigate to={`/login/${rest.location.search}`} replace />
)
const mapStateToProps = (state) => ({
auth: state.auth
})
export default connect(mapStateToProps)(withRouter(ProtectedRoute))
my app.js is like this
function App(props) {
useEffect(() => {
store.dispatch(setCurrentUser())
}, [])
const grabProductsFromStorage = () =>{
const userId = decodeUser().user.id
const cartProducts = JSON.parse(localStorage.getItem("products"))
const context = {products: cartProducts, userId}
store.dispatch(addToCart(context))
localStorage.removeItem("products")
}
if(localStorage.getItem("token") && localStorage.getItem("products")){
grabProductsFromStorage()
}
return (
<Provider store={store}>
<Router>
<Routes>
<Route exact path="/" element={<Landing/>} />
<Route exact path="/products/:id" element={<ProductDetails/>} />
<Route exact path="/" element={<ProtectedRoute/>}>
<Route exact
path="/dashboard/*"
element={<Dashboard {...props} nestedRoute={Home} />}
/>
<Route exact path="/cart" element={<Cart />} />
</Route>
<Route exact path="/register" element={<Register/>} />
<Route exact path="/login" element={<Login/>} />
</Routes>
</Router>
</Provider>
);
}
Also, I've seen somewhere to use state in Navigate with the location it but when I'm doing it it's throwing an error of Unexpected use of 'location'
You need to store that cart route first. while redirecting to login page from the cart if a user is not authenticated & redirected to the login page you need to store the cart route in your localstorage or somewhere in your state so after login you can check do we have afterlogin route then you can redirect the user to that page.
There are some approaches:
Redirect user to another page:
function Redirect() {
let navigate = useNavigate();
function handleClick() {
navigate('/home')
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);
}
redirect to previous page
function Redirect() {
let navigate = useNavigate();
function handleClick() {
navigate(-1)
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);
}
redirect user to the next page
function Redirect() {
let navigate = useNavigate();
function handleClick() {
navigate(1)
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);

Restriction on pages after login in React

So I'm using react router v6 in my React App.
I have the following routes enabled in my app.js file
<Routes>
<Route path='/' component={<Home />} />
<Route path='/login' component={<SignUp />} />
<Route path='/signup' component={<Login />} />
</Routes>
Everything's fine and that. What I want to to do is to put restriction on pages. Now I know how to create PrivateRoutes and PublicRoutes based on LoggedIn User.
For this purpose I want the user to not be able to access Homepage after he or she signups.
Are there an functions for that or what strategy would I use.
I accomplished this using 'react-router-dom' and creating a PrivateRoute component. The following code is not tested but can give you some ideas. LoaderComponent is a loading animation of your choice can be toher component as well.
// Based on https://reactrouter.com/web/example/auth-workflow
// If the user is not yet authenticated.
const PrivateRoute: React.FC<PrivateRouteProps> = ({ children, path, ...props }) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
//put your authentication logic
setIsAuthenticated(true);
}, []);
return (
<Route
path={path}
{...props}
render={() => (isAuthenticated ? children : <LoaderComponent />)}
/>
);
};
And in your router config
import { Switch } from 'react-router-dom';
<Switch>
<PrivateRoute exact path='/'>
<Home />
</PrivateRoute>
...
</Switch>

React js Redirect Function

I am using firebase auth for my React js project. Aim - When the user goes to the path - '/home' , it should check whether the user is logged in or not. If not logged in, redirect to the path - '/' ,or else render the component "Home". But, when I run the code, the functions are working properly but, the component is not rendering on the screen.
Code of App.js -
function App() {
var users;
function checkUserLoggedIn() {
firebase.auth().onAuthStateChanged(function (user) {
users = user;
console.log(users);
users ? <Home /> : <Redirect to="/" />;
});
}
return (
<div className="app">
<Router>
<Switch>
<Route exact path="/">
<Welcome />
</Route>
<Route path="/home">{checkUserLoggedIn()}</Route>
</Switch>
</Router>
</div>
);
}
Any idea why this is not working ?
Thanks !
create a Dictionary file route
and add three files
index.js
publicRoute.js
privateRoute.js
in index.js
/// index.js
import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import PrivateRoutes from './PrivateRoutes'
import PublicRoutes from './PublicRoutes';
function Routes() {
const { pathname } = useLocation();
const[isUserLoggedIn, setLoggedIn] = React.useState(false)
useEffect(() => {
firebase.auth().onAuthStateChanged(function (user) {
users = user;
if(users){
setLoggedIn(true)
}
}, [pathname]);
return isUserLoggedIn ? <PrivateRoutes /> : <PublicRoutes />;
}
export default Routes;
And in publicRoutes.js
// publicRoute.js
import React, { Component } from 'react';
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom';
const loading = (
<div className="pt-3 text-center">
<div className="sk-spinner sk-spinner-pulse"></div>
</div>
)
// Pages
const Login = React.lazy(() => import('../views/pages/login/Login'));
const Register = React.lazy(() => import('../views/pages/register/Register'));
class PublicRoutes extends Component {
render() {
return (
<HashRouter>
<React.Suspense fallback={loading}>
<Switch>
<Route exact path="/register" name="Register Page" render={props => <Register {...props}/>} />
<Route path="/login" name="Login Page" render={props => <Login {...props}/>} />
<Route exact path="/register" name="Register Page" render={props => <Register {...props}/>} />
<Redirect to='/login' />
</Switch>
</React.Suspense>
</HashRouter>
);
}
}
export default PublicRoutes;
In Private Route
/// privateRoute.js
import React, { Component } from 'react';
import { HashRouter, Route, Switch } from 'react-router-dom';
import '../scss/style.scss';
const loading = (
<div className="pt-3 text-center">
<div className="sk-spinner sk-spinner-pulse"></div>
</div>
)
// Containers
const TheLayout = React.lazy(() => import('../containers/TheLayout'));
// Pages
const Page404 = React.lazy(() => import('../views/pages/page404/Page404'));
const Page500 = React.lazy(() => import('../views/pages/page500/Page500'));
class PrivateRoutes extends Component {
render() {
return (
<HashRouter>
<React.Suspense fallback={loading}>
<Switch>
<Route exact path="/404" name="Page 404" render={props => <Page404 {...props}/>} />
<Route exact path="/500" name="Page 500" render={props => <Page500 {...props}/>} />
<Route path="/" name="Home" render={props => <TheLayout {...props}/>} />
</Switch>
</React.Suspense>
</HashRouter>
);
}
}
export default PrivateRoutes;

useHistory - Cannot read property 'push' of undefined

When the home button is pressed I want to redirect it to the home page '/ '. But I am getting this error. What can I do ? :
import { Route, useHistory } from 'react-router-dom/cjs/react-router-dom.min';
const history = useHistory();
const homeButtonOnClickHandler = () =>{
history.push("/");
}
<Router>
<Header homeButtonOnClickHandler={homeButtonOnClickHandler}/>
<Switch>
<Route path='/result'>
<Result
ingredients={ingredients}
total={() => hesapla()}
/>
</Route>
<Route path='/'>
<Home
ingredients={ingredients}
total={() => calculate()}
ingredientAdd={(i) => ingredientAdd(i)}
ingredientRemove={(i) => ingredientRemove(i)}
selectedIngredients={ingredients}
isOrder={number}
/>
</Route>
</Switch>
</Router>
You are trying to use history hook outside of Router. Write your function inside Header component.
Try this inside Header component
const history = useHistory();
const homeButtonOnClickHandler = () =>{
history.push('/');
}
You just need to put hook and handler into component like here: link

Categories