ReactJS production with subfolder, navigation not working properly - node.js

I'm struggling to make my ReactJS production work in a subfolder of my website.
The dashboard works, when I go to http://xx.xx.xx.xx/dashboard it loads, but when I go to
http://xx.xx.xx.xx/dashboard/login I get a 404 not found page. When I host in the main folder it works perfectly.
As far as I know to make it work I have to set the basename of the subfolder in the Router of index.js,
which I did. Am I missing anything? I used "npm run build" to make the production.
index.js
ReactDOM.render(
<MuiThemeProvider theme={getMuiTheme()}>
<Provider store={store}>
<Router basename={"/dashboard"} history={history}>
<App />
</Router>
</Provider>
</MuiThemeProvider>,
document.getElementById("root")
);
App.js
export default function App() {
return (
<div>
<Notifs />
<MainContent />
</div>
);
}
MainContent.js
export default function MainContent() {
return (
<div className="container" style={{ marginTop: 20 }}>
<Switch>
<Route exact path="/" component={Landing} />
<Route path="/login" component={Login} />
<Route component={NoMatch} />
</Switch>
</div>
);
}

Related

How to hide footer and menu when notfound page rendering in Router v6 [duplicate]

This question already has answers here:
How do I render components with different layouts/elements using react-router-dom v6
(2 answers)
Closed 10 months ago.
As you can see I want to hide menu bar and footer when notfound page is rendering .I tried all the other solutions but didn't happen to work in my Scenario. I wanted the Navbar and footer hide in 3 notfound Page. I use react-router version 6 and fuctional App component. Please Help me figure out this solution
`
<Menubar />
<Routes>
<Route path='/' element={<Home />} />
<Route path='/home' element={<Home />} />
<Route path='/inventory/:id' element={
<PrivateRoute>
<Inventory />
</PrivateRoute>
} />
<Route path='/manageinventory' element={
<PrivateRoute>
<ManageInventory />
</PrivateRoute>
} />
<Route path='/addinventory' element={
<PrivateRoute>
<AddInventory />
</PrivateRoute>
} />
<Route path='/myitems' element={
<PrivateRoute>
<MyItems />
</PrivateRoute>
} />
<Route path='/login' element={<Login />} />
<Route path='/register' element={<Register />} />
<Route path='/blogs' element={<Blog />} />
<Route path='*' element={<NotFound />} />
</Routes>
<Footer />
Use a master page that contains Navbar and Footer and each Created component will contains a master page except the notFound Page
{/* Layout component */}
import React from "react";
import Sidebar from "./Navbar ";
import Sidebar from "./Footer ";
const Layout = ({ children}) => {
return (
<>
<Navbar />
<main>{children}</main>
<Footer />
</>
);
};
export default Layout;
and for any new component, you will call the master page
{/* For Home, Inventory, ... components */}
import React from "react";
import Layout from "../components/Layout";
const Home = () => {
return (
<Layout>
{/* your code jsx here */}
</Layout>
);
};
export default DahsboardScreen;

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

Jest enzyme test router with props

I have react application and started covering it with unit tests.
My app file contains:
export default class App extends Component {
render() {
return (
<Provider store={store}>
<Router history={history}>
<div>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/detail/:collectionName/:RecordId/:firmId" component={DetailDialog} />
<Route exact path="/dashboard" component={Dashboard} />
<Route path="/auth-login" component={LogIn} />
<Route path="/auth-register" component={Register} />
<Route path="/user-manager" component={this.props.decoded.role==='Admin' ? Admin : Home} />
</Switch>
</div>
</Router>
</Provider>
);
}
}
I want to make next test: go to login, check href and by href check component.
it.only('test right component is attached', () => {
const wrapper = shallow(<Login loginUser={fn}/>);
const registerLink = wrapper.find("[data-qa='sign-up']").props().href;
const history = jest.fn();
const props = {
decoded: {role: 'Admin'}
}
const router = mount(
<MemoryRouter initialEntries={[registerLink]}>
<App history={history} {...props} />
</MemoryRouter>
);
expect(router.find(Register)).toHaveLength(1);
});
Until mounting everything is ok. But on mount I receive the next error:
console.error
Error: Uncaught [Error: Unable to find node on an unmounted component.]
What am I doing wrong? How can I mount the component and check that Register is inside?
Try to pass a history prop not as a jest.fn(), but as a { push : jest.fn() }

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