I'm quite new to react and react router and I'm encountering a few problems. I want to implement a redirecting functionality so to say but it gives me this.props.history.location is undefined error
index.js - App is wrapped with router here
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './app/App.js';
import Test from "./pages/users/users";
import {BrowserRouter, Redirect, Route, Router, Switch} from "react-router-dom";
import createHistory from "history/createBrowserHistory"
import registerServiceWorker from './registerServiceWorker';
import history from './utilities/history'
const app = (
<Router history={history}>
<Route path="/:currentPage?" component={App} />
</Router>
);
ReactDOM.render(app, document.getElementById('root'));
registerServiceWorker();
App.js -- main application
export class App extends Component {
state = {};
handleChange = () => {
console.log(this.props);
const {user, match, history} = this.props;
const currentPath = match.params.currentPage;
const userIsSigningIn = currentPath === "/" + SIGN_IN_PAGE.path;
console.log(this.state.user);
if (this.state.user && currentPath === "/sign-in") {
// history was passed from client/src/index.js
this.props.history.replace('/remittances');
} else if (currentPath !== "/sign-in" && !this.state.user) {
this.props.history.replace('/sign-in');
}
return;
render() {
//this is our initial page
const {user, match, history} = this.props;
const currentPath = match.params.currentPage;
return (
<div className="page-container">
<Switch>
{/*note: important to pass functions as lambdas */}
<Route path="/sign-in" render={() => <SignInPage attemptSignIn={this.attemptSignIn}/>}/>
<Route path="/inventory" render={() => <InventoryPage/>}/>
<Route path="/remittances" render={() => <RemittancePage/>}/>
<Route path="/inventory" render={() => <RemittancePage/>}/>
<Route path="/users" render={() => <UsersPage/>}/>
</Switch>
{/*render navbar if there is a user and path is not sign-in*/}
{!this.state.user && currentPath !== "/sign-in" &&
<NavBar/>
}
</div>
);
}
}
export default withRouter(App)
Any kind of help will do thank you!
Related
I created a component in my project that consists of a simple button that returns to the previous page, using useNavigate hook.
As it is written in the documentation, just passing -1 as a parameter to the hook would be enough to go back one page. But nothing happens.
The component code:
import { useNavigate } from 'react-router-dom'
import './go-back.styles.scss'
const GoBack = () => {
const navigate = useNavigate()
const handleClick = () => {
navigate(-1)
}
return (
<button
className='go-back'
onClick={handleClick}
>
go back
</button>
)
}
export default GoBack
The app.js code:
import { lazy, Suspense } from 'react'
import { Routes, Route } from 'react-router-dom'
import Header from '../components/header/header.component'
import Footer from '../components/footer/footer.component'
import './App.scss'
const App = () => {
const HomePage = lazy(() => import('../pages/home/home.page'))
const SearchPage = lazy(() => import('../pages/search/search.page'))
const MostraPage = lazy(() => import('../pages/mostra/mostra.page'))
const AuthPage = lazy(() => import('../pages/auth/auth.page'))
const AccountPage = lazy(() => import('../pages/account/account.page'))
const PrenotaPage = lazy(()=> import('../pages/prenota/prenota.page'))
const SectionPage = lazy(() => import('../pages/section/section.page'))
return (
<div className='app'>
<Header />
<Suspense fallback={<span>Loading...</span>}>
<Routes>
<Route exact path='/' element={<HomePage />} />
<Route exact path='/auth:p' element={<AuthPage />} />
<Route exact path='/search' element={<SearchPage />} />
<Route exact path='/search:id' element={<SectionPage />} />
<Route exact path='/mostra' element={<MostraPage />} />
<Route exact path='/prenota' element={<PrenotaPage/>} />
<Route exact path='/profile' element={<AccountPage />} />
<Route exact path='*' element={<span>Page not found</span>} />
</Routes>
</Suspense>
<Footer />
</div>
)
}
export default App
The index.js code:
import { createRoot } from 'react-dom/client'
import { Provider } from 'react-redux'
import store, { persistor } from './redux/store/store'
import App from './app/App'
import reportWebVitals from './reportWebVitals'
import { PersistGate } from 'redux-persist/integration/react'
import { BrowserRouter } from 'react-router-dom'
const container = document.getElementById('root')
const root = createRoot(container)
root.render(
<BrowserRouter>
<Provider store={store}>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>
</BrowserRouter>
)
reportWebVitals()
I thank in advance anyone who tries to help.
In the project, when rendering to another page I used the useNavigate hook and passed { replace: true } as the second parameter.
However, in this way the navigation will replace the current entry in the history stack instead of adding a new one by not then making the GoBack component work properly.
So it was enough to remove { replace: true } from the calls to useNavigate and now it works.
I have a problem with the router V6. The routes are not being rendered. The homepage use to have all the products and now I cannot see any of the products shown, also I have my code to the links that go to every part of the website but is not appearing. The error that appears is:
react_devtools_backend.js:4045 No routes matched location "/rewards-store-andrea-lopez-bravo"
at Routes (http://localhost:3000/rewards-store-andrea-lopez-bravo/static/js/vendors~main.chunk.js:32538:5)
at Router
at div
at App (http://localhost:3000/rewards-store-andrea-lopez-bravo/static/js/main.chunk.js:423:63)
at Router (http://localhost:3000/rewards-store-andrea-lopez-bravo/static/js/vendors~main.chunk.js:32471:15)
at BrowserRouter (http://localhost:3000/rewards-store-andrea-lopez-bravo/static/js/vendors~main.chunk.js:31958:5)
at AppProvider (http://localhost:3000/rewards-store-andrea-lopez-bravo/static/js/main.chunk.js:4188:5)
index.tsx:25 No routes matched location "/rewards-store"
This my router:
import { Routes, Route } from "react-router-dom";
import { Home } from "../pages/Home";
import { History } from "../pages/History";
import { Points } from "../pages/Points";
import { NotFound } from "../components/notification/NotFound";
export const Router = () => {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/history" element={<History/>}/>
<Route path="points" element={<Points/>}/>
<Route path="NotFound" element={<NotFound/>} />
</Routes>
);
};
This is index:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import AppProvider from "./context/AppContext";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<AppProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</AppProvider>
</React.StrictMode>,
document.getElementById("root")
);
AppContext:
import React,{ useState } from "react";
import { usePagination } from "../components/utils/pagination.jsx";
export const AppContext = React.createContext();
export default function AppProvider({ children }) {
const [user,setUser] = useState({})
const [points, setPoints] = useState(0)
const [products, setProducts] = useState([])
const [reedemStatus, setReedemStatus] = useState({})
const [history, setHistory] = useState([])
const paginationList = usePagination(products, 16)
const paginationHistoryList = usePagination(history, 16)
const totalProducts = products.length
const totalHistory = history.length
const handlerAddPoint =(value)=>{
const newUser = {...user}
newUser.points = user.points + value
setUser(newUser)
}
const handlerSubtractPoint =(points)=>{
const newUser = {...user}
newUser.points = user.points - points
setUser(newUser)
}
return(
<AppContext.Provider value={{user,
setUser,
handlerAddPoint,
handlerSubtractPoint,
points,
setPoints,
products,
setProducts,
totalProducts,
paginationList,
reedemStatus,
setReedemStatus,
history,
setHistory,
paginationHistoryList,
totalHistory}}>
{children}
</AppContext.Provider>
);
}
App.js
import React, { useEffect, useContext } from "react";
import "./App.css";
import { Header } from "./components/header/Header";
import { Nav } from "./components/nav/Nav.jsx";
import { getUser } from "./services/users";
import { AppContext } from "./context/AppContext";
import { Notification } from "./components/notification/Notification";
import { Router } from "./routers/Router";
function App() {
const { setUser } = useContext(AppContext);
useEffect(() => {
getUser().then((user) => {
setUser(user);
});
}, [setUser]);
return (
<div className="App">
<Notification />
<Nav />
<Header />
<Router />
</div>
);
}
export default App;
In the menu.jsx the links are not rendering:
import "./Menu.css";
import React from "react";
import { Link } from "react-router-dom";
export const Menu =()=>{
return(
<ul className="menu flex-row">
<li className="pink-line"><Link className="normal-text" to="/acamica-rewards-store/">Home</Link></li>
<li className="pink-line"><Link className="normal-text" to="/acamica-rewards-store/points">Add points</Link></li>
<li className="pink-line"><Link className="normal-text" to="/acamica-rewards-store/history">History</Link></li>
</ul>
)
}
In your router always put the home route at the very bottom!
<Routes>
<Route path="/history" element={<History/>}/>
<Route path="points" element={<Points/>}/>
<Route path="NotFound" element={<NotFound/>} />
<Route path="/" element={<Home />} />
</Routes>
or make sure to make the home path as exact!
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/history" element={<History/>}/>
<Route path="points" element={<Points/>}/>
<Route path="NotFound" element={<NotFound/>} />
</Routes>
I did this in v.6
<Route path="/cart" element={<CartPage />}>
<Route path=":id" element={<CartPage />} />
</Route>
Please help me
When the Route is not inside <Routes> it gives an error:
Error: A is only ever to be used as the child of element, never rendered directly. Please wrap your in a
When it is inside <Routes> it give an error as:
Error: [Abc] is not a <Route> component. All component children of must be a <Route> or <React.Fragment>
Pls help me to resolve this situation? Or any suggestion.
Tried this but one of the above error in both cases.
As this does not generate an error, however my child component of the private route does not render.
import React from 'react'
import './App.css'
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './components/Header'
import Home from './components/Home'
import Login from './components/Login'
import ProtectedRoute from './components/Helper/ProtectedRoute';
import { UserStorage } from './UserContext';
import User from './components/User';
const App = () => {
return (
<div>
<BrowserRouter>
<UserStorage>
<>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="login/*" element={<Login />} />
<Route path='/conta' element={<ProtectedRoute/>}>
<Route path='/conta' element={<User/>}/>
</Route>
</Routes>
</>
</UserStorage>
</BrowserRouter>
</div>
)
}
export default App;
ProtectedRoute
import React from 'react';
import { UserContext } from '../../UserContext';
import {Routes, Route, Navigate } from 'react-router-dom';
const ProtectedRoute = (props) => {
const { login } = React.useContext(UserContext);
if (login === true) return (
<Routes>
<Route {...props} />
</Routes>
);
else if (login === false) return <Navigate to="/login" />;
else return null;
};
export default ProtectedRoute;
With layout wrapper components like ProtectedRoute that renders nested Route components then you need to ensure it is rendering an Outlet for them to be rendered into.
Outlet
import React from 'react';
import { UserContext } from '../../UserContext';
import {Routes, Route, Navigate } from 'react-router-dom';
const ProtectedRoute = () => {
const { login } = React.useContext(UserContext);
if (login === undefined) return null;
return login
? <Outlet /> // <-- nested Route components rendered here
: <Navigate to="/login" replace />;
};
...
<Route path='/conta' element={<ProtectedRoute/>}>
<Route path='/conta' element={<User/>}/> // <-- rendered into outlet
</Route>
Protected Routes.js:
In protected routes you can see I'm using directly false in if statement but I'm still able to see that page why?
import React from 'react';
import { Route } from 'react-router-dom';
// import Auth from './User/Auth';
import Error401 from './Error/401';
// create a component for protected route
console.log('Routes.js');
export const ProtectedRoute = ({ element: Element, ...rest }) => {
console.log("Function Called")
return (
<Route {...rest} render={props => {
if(false){
return <Element {...props} />
}else{
return <Error401 />
}
}
} />
)
}
App.js:
This is app.js where I'm using protected routes component
import './App.css';
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Layout } from 'antd';
import { MoneyCollectOutlined } from '#ant-design/icons';
import Login from './Components/User/Login';
import Signup from './Components/User/Signup';
import {ProtectedRoute} from './Components/Routes';
import Error404 from './Components/Error/404';
function App() {
return (
<BrowserRouter>
<Layout style={{minHeight:"100vh"}}>
<Layout.Header>
<h1 style={{color:"white"}} align="center"> <MoneyCollectOutlined/>MoneyG</h1>
</Layout.Header>
<Layout.Content style={{minHeight:"100%"}}>
<Routes>
<ProtectedRoute exact path="/register" element={<Signup/>} />
<ProtectedRoute exact path="/login" element={<Login/>} />
<Route path="*" element={<Error404/>} />
</Routes>
</Layout.Content>
</Layout>
</BrowserRouter>
);
}
export default App;
First, <Routes> elements should only have <Route> elements as children. You should move your protection logic down a layer.
Secondly, the render prop doesn't exist anymore in V6. It was replaced in favor of element. See doc.
Here is how you might tackle it:
<Routes>
<Route exact path="/register" element={(
<ProtectedRoute>
<Signup/>
</ProtectedRoute>
)} />
<Route exact path="/login" element={(
<ProtectedRoute>
<Login/>
</ProtectedRoute>
)} />
<Route path="*" element={<Error404/>} />
</Routes>
And:
const ProtectedRoute = () => {
if (condition) { return <Error401 />; } // You might as well use Navigate here
return children;
};
you can use createContext & useContext
//store/AuthApi.jsx
import { createContext } from "react";
const AuthApi = createContext();
export default AuthApi;
Then define the context app.jsx
import React, from 'react'
import { AllRoutes } from 'routes/Routes';
import { BrowserRouter as Router } from "react-router-dom";
import AuthApi from 'store/AuthApi';
const App = () => {
const [user, setUser] = useState(false);
useEffect(() => {
// you can get user from localStorage or Cookie(js-cookie npm)
//then you can change user state true or false
}, [])
return (
<>
<AuthApi.Provider value={{ user, setUser }}>
<Router>
<AllRoutes />
</Router>
</AuthApi.Provider>
<Toast />
</>
)
}
export default App
then see AllRoutes
//routes/Routes
import React, { useContext } from "react";
import { Routes, Route } from "react-router-dom";
import { SignIn, SignUp, Dashboard } from "pages";
import AuthApi from "store/AuthApi";
export const ProtectedRouting = () => {
return (
<Routes >
<Route path='/' exact element={<Dashboard />} />
// add more protected routes
</Routes>
)
}
export const AuthRouting = () => {
return (
<Routes >
<Route exact={true} path='/sign-in' element={<SignIn />} />
<Route exact={true} path='/sign-up' element={<SignUp />} />
</Routes>
)
}
export const AllRoutes = ()=> {
const context = useContext(AuthApi);
console.log(context.user)
return (
context.user ?
<ProtectedRouting />
: <AuthRouting />
)
}
pages/SignIn.jsx
import React,{ useContext } from 'react';
import AuthApi from "store/AuthApi";
const SignIn = () => {
const context = useContext(AuthApi);
const signInSubmit =(e)=> {
e.preventDefault();
//post request to signin
// if login is successfull then save user or token in cookie or localStorage or something
context?.setUser(true);
//...
}
return (
//signin code here
<form onSubmit={signInSubmit}>
///input here
</form>
)
}
export default SignIn
I want to make a second private page like links in MeteorJS with react, called landing, create the Landing.js component and import it into the routes file but at the time of going to the route in the browser "http: // localhost: 3000/landing "sends me to the NotFound page, which may be wrong? I would be grateful for the help
'../imports/routes/routes';
import React from 'react';
import Meteor from 'meteor/meteor';
import { Router, Route, browserHistory } from 'react-router';
import Vitae from '../ui/Vitae';
import Logeo from '../ui/Logeo';
import Registro from '../ui/Registro';
import NoEncontrado from '../ui/NoEncontrado';
import Landing from '../ui/Landing';
// flecha tracker
Tracker.autorun(() => {
const paginasUnautenticadas = ['/', '/registro'];
const paginasAutenticadas = ['/vitae', '/landing'];
const enPaginaPublica = () => {
if(Meteor.userId()) {
browserHistory.replace('/vitae');
}
};
const enPaginaPrivada = () => {
if(!Meteor.userId()) {
browserHistory.replace('/');
}
};
export const cambioAutenticacion = (estaAutenticado) => {
const pathname = browserHistory.getCurrentLocation().pathname;
const esPaginaUnautenticada = paginasUnautenticadas.includes(pathname);
const esPaginaAutenticada = paginasAutenticadas.includes(pathname);
if(esPaginaUnautenticada && estaAutenticado) {
browserHistory.replace('/vitae');
} else if (esPaginaAutenticada && !estaAutenticado) {
browserHistory.replace('/');
}
};
export const routes = (
<Router history={browserHistory}>
<Route path="/" component={Logeo}/>
<Route path="/vitae" component={Vitae}/>
<Route path="/registro" component={Registro}/>
<Route path="*" component={NoEncontrado}/>
<Route path="/landing" component={Landing}/>
</Router>
);
});
and my component Landing.js
import React from 'react';
export default class Landing extends React.Component {
render() {
return(
<div>
<h3>Landing Page</h3>
</div>
);
};
}
You have your Landing route after your wildcard "Not Found" route
<Route path="*" component={NoEncontrado}/>
<Route path="/landing" component={Landing}/>
I'm pretty sure that if you switch these two over, it will work as expected :)
<Route path="/landing" component={Landing}/>
<Route path="*" component={NoEncontrado}/>