Routing in Meteor with React & React-Router - javascript

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}/>

Related

React Router v6.4 useNavigate(-1) not going back

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.

Private routes in "react-router-dom": "6.0.0-beta.0"

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>

React-router-dom Protected Routes are not working

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

How to share a websocket between components

I have been studying React for two weeks, and have encountered a problem that I do not know how to solve.
My project is a simple app to talk with other people.
I use to communicate with the server WebSocket, but i do not know how to share one connection of socket between all components in the project.
I tried to write a .js file to share socket by simple export and import this variable to other components, it works but only only in the functions not included in the component.
SocketProvider.js
let socket = new WebSocket("ws://ip:65000/srv");
export default socket;
I need this to properly redirect the user to the appropriate project component.
Login.js
import React, {Component} from 'react';
import {Link} from "react-router-dom";
import socket from "./SocketProvider";
import { Redirect } from 'react-router-dom';
class Login extends Component {
state = {
logged: false
};
login = () => {
const loginInput = document.querySelector('#loginInput').value;
const passwordInput = document.querySelector('#passwordInput').value;
const loginData = {
"type": "login",
"name": loginInput,
"password": passwordInput
}
socket.onopen = () => {
socket.send(JSON.stringify(loginData));
}
socket.onmessage = (e) => {
const socketResponse = JSON.parse(e.data);
const status = socketResponse.status;
if(status==4)
this.setState({logged: true});
};
};
render() {
const { logged } = this.state;
if(logged){
return <Redirect to={"/app"}/>
}
return (
<div>
<div className={"whateverInterface"}>
<h1 className={"whateverInterface__logo"}>LOGIN</h1>
<div className={"whateverInterface__form"}>
<div className="whateverInterface__form--object">Login</div>
<input type="text" className={"whateverInterface__input"} id={"loginInput"}/>
<div className="whateverInterface__form--object">Hasło</div>
<input type="password" className={"whateverInterface__input"}id= {"passwordInput"}/>
</div>
<button className={"whateverInterface__button"} id={"createAccountBtn"}
onClick={this.login}>Login
</button>
<div className={"whateverInterace__controls"}>
</div>
</div>
</div>
);
}
}
export default Login
App.js
import React, {Component} from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import logo from './logo.svg';
import { TransitionGroup, CSSTransition } from "react-transition-group";
import './App.css';
import Error404 from './Error404';
import Login from "./Login";
import Main from "./Main";
import socket from "./SocketProvider";
import Register from "./Register";
import AppInterface from "./Interface";
class App extends Component {
constructor() {
super();
this.state = {
isLogged: true
};
}
render() {
return (
<main>
<Route
render={({location}) => {
const {pathname} = location;
return (
<TransitionGroup>
<CSSTransition
key={pathname}
classNames="fade"
timeout={{
enter: 350,
exit: 350,
}}
>
<Route
location={location}
render={() => (
<Switch>
<div className={"content"}>
<Route path="/whatever-react" component={Main} isLogged={this.state.isLogged} exact />
<Route path="/login" component={Login} exact/>
<Route path="/register" component={Register} exact/>
<Route path="/app" component={AppInterface} exact/>
<Route path='*' exact={true} component={Error404}/>
</div>
</Switch>
)}
/>
</CSSTransition>
</TransitionGroup>
);
}}
/>
</main>
);
}
}
export default App;
App.js is the main component with Route, and Login.js is the component when i tried use socket to properly login to my app. Where do i make a mistake?

React Router this.props.history.location is undefined

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!

Categories