routing problem: my routes on render are not working? - node.js

import Home from "./Pages/home/Home";
import TopBar from "./components/topbar/Topbar.jsx";
import Single from "./Pages/single/Single";
import Write from "./Pages/write/Write";
import Settings from "./Pages/settings/Settings";
import Login from "./Pages/login/Login";
import Register from "./Pages/register/Register";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
function App() {
const user = true;
return (
<Router>
<TopBar />
<Routes>
<Route exact path="/" component={Home} />
<Route path="/register" component={user ? <Home /> :{Register}} />
<Route path="/login" component={user ? <Home /> : {Login}} />
<Route path="/write" component={user ? <Write /> : {Register}} />
<Route path="/settings" component={user ? <Settings /> : {Register}} />
<Route path="/post/:Id" component={Single} />
</Routes>
</Router>
);
}
export default App;
This is my code but the homepage isnt rendering apart from topbar how do i resolve this. Am not sure if the syntax is correct.

Yeah, the syntax is a little mixed up. In react-router-dom version 6 the Route components render their components on the element prop as JSX, not on any component or render prop as a reference to a React component or function that returns JSX.
function App() {
const user = true;
return (
<Router>
<TopBar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/register" element={user ? <Home /> : <Register />} />
<Route path="/login" element={user ? <Home /> : <Login />} />
<Route path="/write" element={user ? <Write /> : <Register />} />
<Route path="/settings" element={user ? <Settings /> : <Register />} />
<Route path="/post/:Id" element={<Single />} />
</Routes>
</Router>
);
}

Related

Provider.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object

When I try to run the website it shows the error in the this line and says it is not valid
ReactDOM.render(<App />, document.getElementById("root"));
Here is the App component in App.js file
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<SideBar />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/signup" component={Signup} />
<Route exact path="/login" component={Login} />
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/dashboard/course" component={Course} />
<Route
exact
path="/dashboard/course/lectures"
component={Lecture}
/>
<Route
exact
path="/dashboard/course/discussion"
component={Discussion}
/>
<Route component={NotFound} />
</Switch>
<DeletePopup />
</Router>
</Provider>
);
}
}

how to set condition in react router DOM version 6?

I want to convert this code which has been written in react router v5 to v6 but I don't know how to do it, in general I want to set if the user doesn't have an account, redirect them to registration page an so on.
I'm aware of switch change and redirect the only problem is in this line of code :
<Route exact path="/">
{user ? <Home /> : <Redirect to="/register" />}
</Route>
the whole code:
import "./app.scss";
import Home from "./pages/home/Home";
import Register from "./pages/register/Register";
import Watch from "./pages/watch/Watch";
import Login from "./pages/login/Login";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import { useContext } from "react";
import { AuthContext } from "./authContext/AuthContext";
const App = () => {
const { user } = useContext(AuthContext);
return (
<Router>
<Switch>
<Route exact path="/">
{user ? <Home /> : <Redirect to="/register" />}
</Route>
<Route path="/register">
{!user ? <Register /> : <Redirect to="/" />}
</Route>
<Route path="/login">{!user ? <Login /> : <Redirect to="/" />}</Route>
{user && (
<>
<Route path="/movies">
<Home type="movie" />
</Route>
<Route path="/series">
<Home type="series" />
</Route>
<Route path="/watch">
<Watch />
</Route>
</>
)}
</Switch>
</Router>
);
};
export default App;
You can use the element prop of v6, you don't need to use an exact prop on <Route path="/"> anymore. This is because all paths match exactly by default. If you want to match more of the URL because you have child routes use a trailing * as <Route path="/*" />.
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
.
.
.
return (
<BrowserRouter>
<Routes>
<Route path="/" element={user ? <Home /> : <Navigate to="/register" replace />} />
.
.
.
</Routes>
</BrowserRouter>
)
.
.
.
Also you can see more detail in reactrouter docs:
https://reactrouter.com/docs/en/v6/getting-started/overview

How to set redirect?

I have Switch component
<Switch>
<Route path="/contacts" exact>
<ContactsPage />
</Route>
<Route path="/add" exact>
<AddContactForm />
</Route>
<Redirect to="/contacts" />
</Switch>
Now when I go to /contacts/add it redirects me to /contacts.
But I need to do redirect only if no one of routes is true.
So how to do that?
You need to write whole route not only /add -> /contact/add
<Switch>
<Route path="/contacts/add" exact>
<AddContactForm />
</Route>
<Route path="/contacts" exact>
<ContactsPage />
</Route>
<Redirect to="/contacts" />
</Switch>
Or if you want to split global router to few small routers
// Router.js
<Switch>
<Route path="/contacts"> // remove exact
<ContactsPage />
</Route>
<Redirect to="/contacts" />
</Switch>
then inside Contacts page:
// ContactsPage.js
<Switch>
<Route path="/contacts/add" exact>
<AddContactForm />
</Route>
<Route path="/contacts" exact>
<Contacts />
</Route>
</Switch>

Load different routes on beta server than on main server?

I'm using react and react-router-dom for my website. I have two versions of the site, one that it for beta users and the other that is for my customers. When the site is loaded on the beta server with process.env.IS_BETA === "true" I only want users to be able to access the login and forgot my password pages. I don't want them to access the registration page or the front page. I tried the following but it didn't work because I think the process.env is already read when it's built.
export const App = () => (
<BrowserRouter>
<div className="d-flex flex-column height-100vh">
<Navbar />
{process.env.IS_BETA === "true" && (
<Switch>
<Route path="/PrivacyPolicy" component={PrivacyPolicy} />
<Route path="/TermsOfUse" component={TermsOfUse} />
<Route path="/Login" component={Login} />
<Route path="/Forgot" component={Forgot} />
<Route path="/Reset" component={Reset} />
<Redirect to="/Login" />
</Switch>
)}
{process.env.IS_BETA !== "true" && (
<Switch>
<Route exact path="/" component={Home} />
<Route path="/PrivacyPolicy" component={PrivacyPolicy} />
<Route path="/TermsOfUse" component={TermsOfUse} />
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
<Route path="/Forgot" component={Forgot} />
<Route path="/Reset" component={Reset} />
<Redirect to="/" />
</Switch>
)}
<Footer />
</div>
</BrowserRouter>
);
How do I redirect or not load some pages on the beta server?
process.env is not available direclty in your Javascript code, but it will be available to Webpack at compile time. Webpack supports defining globals within your Javascript environment with the DefinePlugin, so by adding a new plugin definition as follows:
plugins: [
new webpack.DefinePlugin({
__IS_BETA__: process.env.IS_BETA === "true",
}),
],
in your Webpack config, __IS_BETA__ will be replaced throughout your Javascript code based on whether IS_BETA environment variable was set to true when compiling your app.
You can then reference it in your React code as such:
export const App = () => (
<BrowserRouter>
<div className="d-flex flex-column height-100vh">
<Navbar />
{__IS_BETA__ && (
<Switch>
<Route path="/PrivacyPolicy" component={PrivacyPolicy} />
<Route path="/TermsOfUse" component={TermsOfUse} />
<Route path="/Login" component={Login} />
<Route path="/Forgot" component={Forgot} />
<Route path="/Reset" component={Reset} />
<Redirect to="/Login" />
</Switch>
)}
{!__IS_BETA__ && (
<Switch>
<Route exact path="/" component={Home} />
<Route path="/PrivacyPolicy" component={PrivacyPolicy} />
<Route path="/TermsOfUse" component={TermsOfUse} />
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
<Route path="/Forgot" component={Forgot} />
<Route path="/Reset" component={Reset} />
<Redirect to="/" />
</Switch>
)}
<Footer />
</div>
</BrowserRouter>
);

How can I make the 404 route work in React-Router?

I am trying to make a 404 route with react-router and it doesn't work.
I tried <Route path="*" component={PageNotFound} /> and <Route component={PageNotFound} /> and wrapped all my routes with <Switch></Switch.
My guess is that it doesn't work because I have two <Switch /> components nested inside each other.
App.js:
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Header />
<Switch>
<Route exact path="/" component={Landing} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profiles" component={Profiles} />
<Route exact path="/profile/:id" component={Profile} />
<Switch>
<PrivateRoute exact path="/dashboard" component={Dashboard} />
</Switch>
<Switch>
<PrivateRoute exact path="/posts" component={Posts} />
</Switch>
<Switch>
<PrivateRoute exact path="/post/:id" component={Post} />
</Switch>
<Switch>
<PrivateRoute
exact
path="/create-profile"
component={CreateProfile}
/>
</Switch>
<Switch>
<PrivateRoute
exact
path="/edit-profile"
component={EditProfile}
/>
</Switch>
<Route path="*" component={PageNotFound} />
</Switch>
<Footer />
</div>
</Router>
</Provider>
);
}
}
PrivateRoute.js:
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
<Route
{...rest}
render={props =>
auth.isAuthenticated === true ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
);
I also tried putting the 404 route just above the first <PrivateRoute />. And it works for the non-private routes but I want it to work in all routes.
The example above also messes up the <PrivateRoute exact path="/posts" component={Posts} /> route.
You can view the website at https://floating-waters-33077.herokuapp.com
I think the issue is the number of Switch blocks you have. You should ideally only have one.
Since each route is exact you can condense your Switch component children to
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Header />
<Switch>
<Route exact path="/" component={Landing} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profiles" component={Profiles} />
<Route exact path="/profile/:id" component={Profile} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute exact path="/posts" component={Posts} />
<PrivateRoute exact path="/post/:id" component={Post} />
<PrivateRoute
exact
path="/create-profile"
component={CreateProfile}
/>
<PrivateRoute
exact
path="/edit-profile"
component={EditProfile}
/>
<Route component={PageNotFound} />
</Switch>
<Footer />
</div>
</Router>
</Provider>
);
}
}
This will allow for the 404 page to be a catch-all if none of the routes match in the overall Switch block.

Resources