Unable to change view on sidebar button click - React - javascript

I'm pretty new to react. It's been only a few days since I started react.
I have a question regarding routing. I'm trying to change the main content on the sidebar button click. I think I'm doing something wrong with linking pages right.
In below Sidebar.js class, I am linking the dashboard page on button click with to="/admin/dashboard"
Below is the Sidebar.js class
import React from "react";
import { Link } from "react-router-dom";
const Sidebar = () => {
return (
<nav className="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div className="sb-sidenav-menu">
<div className="nav">
<div className="sb-sidenav-menu-heading">Core</div>
<Link className="nav-link" to="/admin/dashboard"> // <<<--- Here I'm linking button
<div className="sb-nav-link-icon">
<i className="fas fa-tachometer-alt"></i>
</div>
Dashboard
</Link>
......... Similar type of code .......
</div>
</div>
<div className="sb-sidenav-footer">
<div className="small">Logged in as:</div>
Ecommerce React Laravel admin
</div>
</nav>
);
};
export default Sidebar;
Below is App.js
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import MasterLayout from "./layouts/admin/MasterLayout";
import Home from "./components/frontend/Home";
function App() {
return (
<div className="App">
<h1>Hello</h1>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route
path="/admin/*"
name="Admin"
element={<MasterLayout />}
/>
</Routes>
</Router>
</div>
);
}
export default App;
Below is the MasterLayout.js
import React from "react";
import { Navigate, Route, Routes, Router } from "react-router-dom";
import "../../assets/admin/css/styles.css";
import "../../assets/admin/js/scripts";
import Navbar from "./Navbar";
import Sidebar from "./Sidebar";
import Footer from "./Footer";
import routes from "../../routes/routes";
import Dashboard from "../../components/admin/Dashboard";
const MasterLayout = () => {
return (
<div className="sb-nav-fixed">
<Navbar />
<div id="layoutSidenav">
<div id="layoutSidenav_nav">
<Sidebar />
</div>
<div id="layoutSidenav_content">
<main>
<Routes>
{ routes.map((route, idx) => {
return (
route.element && (
<Route
key={idx}
path={route.path}
name={route.name}
element={route.element}
/>
)
);
})}
</Routes>
</main>
</div>
</div>
</div>
);
};
export default MasterLayout;
Below is the routes.js class
const routes = [
{
path: "/admin/dashboard",
name: "Dashboard",
element: <Dashboard />,
},
{
path: "/admin/profile",
name: "Profile",
element: <Profile />,
},
{ path: "/", name: "Admin", element: <Dashboard /> },
];
Below is dashboard.js
import React from "react";
function Dashboard() {
return <h1>I'm Dashboard</h1>;
}
export default Dashboard;
Below is the file directory
This link is changing as desired. Browser URL look as expected when clicking the link

The element prop takes a ReactNode, a.k.a. JSX. Instead of passing a reference to a React component pass it as JSX. The routes should also be relative from the /"admin/*" path rendered in App.
const routes = [
{ path: "/", name: "Admin", element: <Dashboard /> },
{
path: "dashboard",
name: "Dashboard",
element: <Dashboard />,
},
{
path: "profile",
name: "Profile",
element: <Profile />,
},
];

Related

Nested routing in react is not rendering nested component

Nested routing is not working. 'Landing' And 'home' components showing properly but nested components are not rendering.
The layout component is directly imported in app.js
there is no error in the console but nested components such as 'Feed' and 'Myprofile' are not rendering.
see the code
import React from 'react';
import { Route, Switch, BrowserRouter as Router} from 'react-router-dom';
import Sidebar from '../componants/Sidebar'
import Navbar from '../componants/Navbar';
import PathRouter from '../Routers/PathRouters'
import Landing from '../pages/Landing';
const Home=()=>{
return(
<>
<div className="container-fluid">
<Navbar />
<div className="rows row">
<div className='col-3'>
<Sidebar />
</div>
<div className="col-9 ">
<div className="content">
<Switch>
{PathRouter.map((prop, key) => {
return (
<Route
exact path={prop.path}
component={prop.component}
key={key}
/>
);
}
)}
</Switch>
</div>
</div>
</div>
</div>
</>
)
}
const Layout = () => {
return (
<>
<Router>
<Switch>
<Route exact path='/' component={Landing} />
<Route exact path='/home' component={Home} />
</Switch>
</Router>
</>
)
}
export default Layout;
This is Pathrouter.js
import Feed from '../pages/Feed';
import Answer from '../pages/Answer';
import Addquestion from '../componants/Addquestion';
import Myprofile from '../componants/Myprofile';
var PathRouter = [
{
path: '/home/feed',
name: 'Feed',
component: Feed
},
{
path: '/home/answer/:q_id',
name: 'answer',
component: Answer
},
{
path: '/home/addquestion',
name: 'addquestion',
component: Addquestion
},
{
path: '/home/myprofile',
name: 'myprofile',
component: Myprofile
}
]
export default PathRouter;
In the Layout component the line <Route exact path='/home' component={Home} /> is breaking your nested routes. For the nested route to render the parent route must also render, since '/home/feed' does not exactly match '/home' the parent route will not be rendered. Remove exact from the '/home' route. – Jacob Smit

Refreshing page with onClick event returns page does not exist

I have a list of posts and when the user clicks on the title he should be navigated to the current post by using the post id as an url. My Link does changes the url, but it does not update the page and the user is not redirected so I am trying to hook an onClick event that also refreshes the page, but when I do that the url is no longer the id of the post and I get a 404 that the page does not exist. How can I refresh the page successfully after the user has clicked on the Link?
Here is my parent component:
import React, { Component } from 'react'
import { NavLink, Route, BrowserRouter } from 'react-router-dom';
import Planets from '../Planets/Planets.jsx';
import Signs from '../Signs/Signs.jsx';
import PlanetaryAspects from '../PlanetaryAspects/PlanetaryAspects.jsx';
import Houses from '../Houses/Houses.jsx';
class BlogCategoriesMenu extends Component {
render() {
return(
<div className="blog-categories-menu">
<BrowserRouter>
<div className="blog-categories-menu__items">
<NavLink to="/planets" className="blog-categories-menu__items-a" activeClassName="isActive">Planets</NavLink>
<NavLink to="/signs" className="blog-categories-menu__items-a" activeClassName="isActive">Signs</NavLink>
<NavLink to="/planetary-aspects" className="blog-categories-menu__items-a" activeClassName="isActive">Planetary Aspects</NavLink>
<NavLink to="/houses" className="blog-categories-menu__items-a" activeClassName="isActive">Houses</NavLink>
<div className="content-container">
<Route path="/planets" component={Planets}></Route>
<Route path="/signs" component={Signs}></Route>
<Route path="/planetary-aspects" component={PlanetaryAspects}></Route>
<Route path="/houses" component={Houses}></Route>
</div>
</div>
</BrowserRouter>
</div>
)
}
}
export default BlogCategoriesMenu;
Here is component that the user clicks:
import React, { Component } from 'react'
import axios from 'axios';
import Spinner from '../Spinner/Spinner';
import { Link, Switch } from 'react-router-dom';
class Planets extends Component {
state = {
posts: [],
currentPage: 1,
setCurrentPage: 1,
postsPerPage: 5,
loading: false
}
componentDidMount() {
const fetchPosts = async () => {
this.setState({...this.state, loading: true});
const res = await axios.get('https://app-endpoint/');
this.setState({...this.state, posts: res.data, loading: false});
};
fetchPosts();
}
reloadPage = () => {
window.location.reload()
}
render() {
const retrogradesPosts = this.state.posts.filter( (item) => {
return item.categories === 'retrogrades'
})
if(this.state.loading) {
return <Spinner/>
}
return(
<div className="planet-articles-container">
<div className="">
<div className="">
{retrogradesPosts.map(post => (
<div key={post._id} className="planet-articles-container__post">
<img className="planet-articles-container__post-img" src={post.picture} alt="avatar"/>
<div className="">
<div className="">
<h2 className="">{post.date}</h2>
<Link to={`/post/${post._id}`} onClick={this.reloadPage}> <p className="">{post.title}</p></Link>
<p className="planet-articles-container__post-text">{post.postContent.substring(0, 100) + "..."}</p>
</div>
</div>
</div>
))}
</div>
</div>
</div>
)
}
}
export default Planets;
and my App.js:
import React from 'react';
import { BrowserRouter, Route, Switch} from 'react-router-dom';
import Home from './components/Home/Home.jsx'
import Error from './components/Error/Error.jsx';
import Blog from './components//Blog//Blog.jsx';
import Post from './components/Post/Post.jsx';
const App = () => {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/blog" component={Blog} exact/>
<Route path="/post/:id" component={Post} exact/>
<Route component={Error}/>
</Switch>
</BrowserRouter>
);
};
export default App;
Is the BlogCatergoriesMenu rendered using /blog?
If BlogCatergoriesMenu is rendered inside the App and this "App Component" is wrapped by BrowserRouter then remove the BrowserRouter in BlogCatergoriesMenu to make it work.
Your updated BlogCatergoriesMenu will look something like this
import React, { Component } from 'react'
import { NavLink, Route } from 'react-router-dom';
import Planets from '../Planets/Planets.jsx';
import Signs from '../Signs/Signs.jsx';
import PlanetaryAspects from '../PlanetaryAspects/PlanetaryAspects.jsx';
import Houses from '../Houses/Houses.jsx';
class BlogCategoriesMenu extends Component {
render() {
return(
<div className="blog-categories-menu">
<div className="blog-categories-menu__items">
<NavLink to="/planets" className="blog-categories-menu__items-a" activeClassName="isActive">Planets</NavLink>
<NavLink to="/signs" className="blog-categories-menu__items-a" activeClassName="isActive">Signs</NavLink>
<NavLink to="/planetary-aspects" className="blog-categories-menu__items-a" activeClassName="isActive">Planetary Aspects</NavLink>
<NavLink to="/houses" className="blog-categories-menu__items-a" activeClassName="isActive">Houses</NavLink>
<div className="content-container">
<Route path="/planets" component={Planets}></Route>
<Route path="/signs" component={Signs}></Route>
<Route path="/planetary-aspects" component={PlanetaryAspects}></Route>
<Route path="/houses" component={Houses}></Route>
</div>
</div>
</div>
)
}
}
export default BlogCategoriesMenu;

How to implement dynamic pages in React.js?

import React, { Component } from "react";
import { FormattedMessage } from "react-intl";
import { connect } from "react-redux";
class Project extends Component {
render() {
return (
<div
className={
"ih-item square effect6 from_top_and_bottom grid-item " +
this.props.category +
" " +
this.props.widthClass
}
>
<FormattedMessage id="route.project">
{route => {
return (
<a href={"/" + route + this.props.url}>
<div className="img">
<img src={this.props.mainImage} alt="img" />
</div>
<div className="info">
<h3>{this.props.header}</h3>
<p>{this.props.description}</p>
</div>
</a>
);
}}
</FormattedMessage>
</div>
);
}
}
const mapStateToProps = state => {
return {
projects: state.project.projects
};
};
export default connect(
mapStateToProps,
{}
)(Project);
How to implement projects' pages and custom URL for every one. I suppose custom URLs have to be done with MongoDB, but how to implement it in reactjs. That is third day of my research, but mostly I found complicated code
Thanks for every answer
You would most likely use a client-side navigation package such as React-Router to accomplish this.
In order to set up a basic router, you need to define routes and views for those routes in the following fashion, where the "path" prop refers to your desired endpoint and "component" being the desired view:
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const BasicExample = () => (
<Router>
<div>
{/* Navigation menu */}
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
</ul>
<hr />
{/* Routes */}
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
);
These routes can also be dynamically-generated using an array of routes, such as the following (defined in your component state):
routes = [
{
path: "/",
exact: true,
component: Home
},
{
path: "/bubblegum",
component: () => <div>bubblegum!</div>,
},
{
path: "/shoelaces",
component: Shoelaces
}
and then rendered in React using .map():
{this.state.routes.map(route => (
<Route exact={route.exact||false} path={route.path} component={route.component} />
))}
I think you need to install react-router-dom.
Second, please use template strings.

ReactJS with React Router single page application SPA with separate login page

I am new to React and React Router. I have been trying to create a single page application that has a layout with navigation bars and content and a login page that does not load inside this layout. I have been searching the web and stackoverflow, but have not been able to figure this out. To create my app, I used "yarn create react-app appName" and use "yarn add" to add react router. How do I need to create my routes such that I have a login page with its own layout and a main layout where my content can be displayed.
Here is my index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
Here is my App.js:
import React, { Component } from 'react';
import Main from "./Main";
import Login, {fakeAuth} from "./components/Login";
import {
Route,
NavLink,
HashRouter,
Redirect,
withRouter,
Switch,
BrowserRouter
} from "react-router-dom";
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Main} />
<Route path="/login" component={Login} />
</Switch>
</BrowserRouter>
);
}
}
export default App;
Here is my Login.js:
import React from 'react';
import {
Route,
NavLink,
HashRouter,
Redirect
} from "react-router-dom";
class Login extends React.Component {
constructor() {
super();
this.state = {
redirectToReferrer: false
}
this.login = this.login.bind(this);
}
login() {
fakeAuth.authenticate(() => {
this.setState({ redirectToReferrer: true })
})
}
render() {
const { from } = this.props.location.state || { from: {
pathname: '/' } }
const { redirectToReferrer } = this.state;
if (redirectToReferrer) {
return (
<Redirect to={from} />
)
}
return (
<div>
<p>You must log in to view the page at {from.pathname}</p>
<button onClick={this.login}>Log in</button>
</div>
)
}
}
/* A fake authentication function */
export const fakeAuth = {
isAuthenticated: false,
authenticate(cb) {
this.isAuthenticated = true;
setTimeout(cb, 100);
}
};
export default Login
Here is my Main.js:
import React, { Component } from 'react';
import Navigation from './components/Navigation'
import LeftSidebar from './components/LeftSidebar';
import RightSidebar from './components/RightSidebar';
import Login, {fakeAuth} from "./components/Login";
import {
Route,
NavLink,
HashRouter,
Redirect,
withRouter,
Switch
} from "react-router-dom";
/* Home component */
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
/* Category component */
const Category = () => (
<div>
<h2>Category</h2>
</div>
)
/* Products component */
const Products = () => (
<div>
<h2>Products</h2>
</div>
)
class Main extends Component {
render() {
return (
<HashRouter>
<div className="container container-fluid">
<Navigation/>
<div className="row">
<div className="col-md-3">
<LeftSidebar/>
</div>
<div className="col-md-6">
<Route exact path="/" component={Home} />
<Route path="/category" component={Category}/>
<PrivateRoute authed={fakeAuth.isAuthenticated} path='/products' component = {Products} />
</div>
<div className="col-md-3">
<RightSidebar/>
</div>
</div>
</div>
</HashRouter>
);
}
}
const PrivateRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated === true ? (
<Component {...props} />
) : (
<Redirect
to={{ pathname: "/login", state: { from: props.location }
}}
/>
)}
/>
);
};
const AuthButton = withRouter(
({ history }) =>
fakeAuth.isAuthenticated ? (
<p>
Welcome!{" "}
<button
onClick={() => {
fakeAuth.signout(() => history.push("/"));
}}
>
Sign out
</button>
</p>
) : (
<p>You are not logged in.</p>
)
);
export default Main;
My links to the routes are in my navigation component:
....
<ul>
<li><Link to="/">Homes</Link></li>
<li><Link to="/category">Category</Link></li>
<li><Link to="/products">Products</Link></li>
</ul>
....
When I click the Home, Category, or Products link, I want the component to load in the SPA layout in Main.js and I want Login.js to load in its own page. Right now, Home, Category, Products, and Login are loading in the main layout. What do I need to change about these routes or other part of my code to get this working?
Edit:
Added my auth code in the Main.js class.
Added Login.js class.
In addition to following some tutorials on this, I have been following the advice from this answer:
Login Page Separated From Single-page Application (SPA) in ReactJS
However, I am not quite getting it. I am not sure exactly what I need to add to make this work.
Here are images illustrating what I am trying to do:
Main.js:
main SPA layout
Login.js:
Login page
Current issue is login is loading in the main layout rather than its own page:
Do NOT want this

React App not routing to the link

I am new to React and having issues with router. I am just learning from this tutorial: https://medium.com/#thejasonfile/basic-intro-to-react-router-v4-a08ae1ba5c42
Below is the code that is being called from my index.html. When I click on the link 'Show the list', the url changes from localhost:8080 to localhost:8080/list but doesn't really change the context of the page. I am not sure what is going or what I am doing wrong here. Any ideas?
Scripts.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Title, App} from './Components/App';
import { BrowserRouter as Router, Route } from 'react-router-dom';
ReactDOM.render(
<Router>
<div>
<Route exact path="/" component={Title} />
<Route path="/list" component={App} />
</div>
</Router>
, document.getElementById('app'));
App.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
const Title = () => {
return (
<div className="title">
<h1>React Router demo</h1>
<Link to="/list">
<button>Show the List</button>
</Link>
</div>
)};
const List = () => {
return (
<div className="nav">
<ul>
<li>list item</li><li>list item</li></ul><Link to="/"><button>Back Home</button></Link></div>)
}
module.exports = {
Title,
List
};
I refactored your code a bit, you should not render the App component for a single page rather your app component should have all the routes like how I made it below. Then as needed add Link throughout your components when you need to navigate and then add the routes in App respectively.
import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { Link } from 'react-router-dom';
class App extends Component {
constructor() {
super();
}
render() {
return (
<Router>
<div>
<Route exact path='/home' render={()=> <Title />} > </Route>
<Route exact path='/list' render={() => <List />} > </Route>
</div>
</Router>
);
}
}
const Title = () => {
return (
<div className="title">
<h1>React Router demo</h1>
<Link to="/list">
<button>Show the List</button>
</Link>
</div>
)};
const List = () => {
return (
<div className="nav">
<ul>
<li>list item</li><li>list item</li></ul><Link to='/home'><button>Back Home</button></Link></div>)
}
render(<App />, document.getElementById('app'));
document.getElementById is usually root looks like you changed it to app which is fine.

Categories