execute route change from siblings component in React Router V4 - reactjs

I am learning React.js. I am using React router version 4.3.1 and React router dom 4.3.1.
My current app structure is given below.
<React.Fragment>
{/* sidebar component */}
<SideBar store = {Mystore} />
<div className="main-panel">
{/* navbar component */}
<NavBar store = {Mystore}/>
{/* content component */}
<Content store = {Mystore}/>
{/* footer component */}
</div>
</React.Fragment>
in my content component i have a Router set up as given below.
<BrowserRouter>
<React.Fragment>
<Route exact path="/phoenix/public" component={Login} />
<ProtectedRoute exact path="/phoenix/public/sample" component={SamplePage} />
<ProtectedRoute exact path="/phoenix/public/view_ticket" component={ViewTicket} />
<ProtectedRoute exact path="/phoenix/public/create_ticket" component={CreateTicket} />
<ProtectedRoute exact path="/phoenix/public/dashboard" component={Dashborad} />
</React.Fragment>
</BrowserRouter>
Here ProtectedRoute is a functional component which checks if the user is authenticated and returns a Route
My sidebar has some a tags like below.
<li>
<a href="dashboard">
<i className="ti-panel" />
<p>Dashboard</p>
</a>
</li>
My goal is to navigate to different Routes without page refresh on click from side bar. But clicking href reloads the page and all my state in my Mobx refreshes. I have tried to Redirect but could not get the Router which is stated in siblings component (content is siblings of sidebar). I have no idea how to achieve this.

As stated in the comments on your question, regular <a> tags will not work, and refresh the page. So you will need to use Link or NavLink.
If you want to make it work in your sidebar (child component) you will need to wrap the <BrowserRouter> around all the components where you want to use the routes.
For example like this (using your code):
<BrowserRouter>
<React.Fragment>
{/* sidebar component */}
<SideBar store = {Mystore} />
<div className="main-panel">
{/* navbar component */}
<NavBar store = {Mystore}/>
{/* content component */}
<Content store = {Mystore}/>
{/* footer component */}
</div>
</React.Fragment>
</BrowserRouter>
And your Sidebar will be something like this:
<React.Fragment>
<Link to="/dashboard">Dashboard</Link>
...
</React.Fragment>
Then in your content component. You need to delete the <BrowserRouter>

I fixed my problem by having BrowserRouter like below as suggested by #PreDinnerSnack.
<BrowserRouter>
<React.Fragment>
{/* sidebar component */}
<SideBar store = {Mystore} />
<div className="main-panel">
{/* navbar component */}
<NavBar store = {Mystore}/>
{/* content component */}
<Content store = {Mystore}/>
{/* footer component */}
</div>
</React.Fragment>
</BrowserRouter>
Then i used Navlink in My Sidebar component. Which fixed the problem of navigating to the desired route without page refresh. But then i faced another problem as Content was not Refreshing according to the route.
For that problem I found the observer HOC of Mobx was interfering with my router. I had to wrap my content with withRouter as below to fix this problem.
withRouter(observer(Content));
I hope my solution will come in handy for someone as i found no tutorial with the examples of React Router implementation like mine on the web.

Related

Route to another component and page when click on an image reactjs

Expected: when clicking on the image from one component(PhotosList), it routes to another page with the specified url to view the other component(Image details)
Reality: what happens that when clicking on the image, both components are rendered on the same page but with the different url.
using import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
Here's the return of the functional component(PhotosList)
return (
<Router>
<div className="layout">
<Masonry gutter={"5 px"} columnsCount={3}>
{photosList.map((photo: any) => (
<Link to={"/details"}>
<img src={photo.download_url} />
</Link>
))}
</Masonry>
<button onClick={loadMore} className="btn-grad">
{isLoading ? "Loading..." : "Load More"}
</button>
<Switch>
<Route exact path={"/details"} component={ImageDetails}></Route>
</Switch>
</div>
</Router>
);
and the app file is
const App = () => {
return (
<div className="App">
<header>Album</header>
<PhotosList />
</div>
);
};
export default App;
return (
<div className="layout">
<Masonry gutter={"5 px"} columnsCount={3}>
{photosList.map((photo: any) => (
<Link to={"/details"}>
<img src={photo.download_url} />
</Link>
))}
</Masonry>
<button onClick={loadMore} className="btn-grad">
{isLoading ? "Loading..." : "Load More"}
</button>
</div>
);
and in the app file
const App = () => {
return (
<Router>
<div className="App">
<header>Album</header>
<PhotosList />
<Switch>
<Route exact path={"/photilist"} component={PhotosList}></Route>
<Route exact path={"/details"} component={ImageDetails}></Route>
</Switch>
</div>
</Router>
);
};
export default App;
From what I can gather, you have rendered the PhotoList component which then renders a list of photos each with a link to /details.
In the same component you set up the /details route.
Whenever you click the Link which redirects to /details, the PhotoList component will (should) unmount. Once this component is unmounted, so is the Route which sets up the component which should be rendered on /details route. So you are on /details but the router has no idea what component should be rendered because the following code:
<Switch>
<Route exact path={"/details"} component={ImageDetails}></Route>
</Switch>
no longer exists.
To avoid this, don't put Routes this far down in your application. Routes should always be close to the top level (children/grandchildren of Router). This makes projects way easier to manage. I do have projects with upwards of 100 routes and I do split up my routes into seperate files (for example each module will have a ModuleRoutes.js file in which I set up the routes for that module), then you can create a RootRouter components which renders these seperate JS files (Which are really React components) and you render the RootRouter inside of your <BrowserRouter> / <Router>.
You can abstract this even higher by creating an array of objects which hold details about each route (route name, path, component for the route, function / data you want to pass down to the component, access control (true/false) defined as a logical expression of your choosing - i.e. user.isLoggedIn === true). By employing this abstraction you minimize the room for error because errors and bugs are much easier to spot when they are in this kind of form (object) as opposed to JSx which takes up more lines of code, has messy indentation and is not very clean in general.

React change component inside de main div based on Sidebar link

I`m beginner in React and I want to create page where I include a Navbar and Sidebar and the main to by changed by Sidebar link. How I do that?
exemple:
import Sidebar from '../Sidebar';
import Navbar from '../Navbar;
import {Page1,Page2,Page3} from './menu'
export default function UserPage(){
return(
<>
<Navbar />
<Sidebar />
<div>
//Here i want to component be loaded based on Navlink
</div>
</>
)
}
I found the problem!
If you keep the navbar or sidebar in path="/" don`t use exact in the route because when you will go to "/dashboard" he will not add them
Use a Router
For routing in react you can look up react router here
You then define your routes and that will fill your content based on url.
Example
See how this is like a normal react component, each route will load some specified components. Anything that exists on every page can be put outside of the Switch component. You cna see the Nav bar here that will exist on every page.
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}

How to decouple the Router and Navbar so the Navbar component is not including components

I am creating a portfolio website, where in this design, I have a background for the entire website that will stay fixed as content scrolls over it. The Navbar is also fixed, and has the content scrolling under it.
This design looks cool, and wasn't too hard to put together, but I am having a little bit of trouble incorporating React Routing into this mix.
From what I gathered, the tutorials say to create a App-Router component, which basically looks like their way of saying "Navbar". So I did that and got my Navbar to route to my Home, and About Me component pages. However, since my Navbar is fixed, all the pages refuse to scroll, which means they are being included inside the Navbar component. This is the opposite of what I want to have happen.
My Ideal setup would be to have the Navigation Bar (It's own component) send a routing request to a Routing component, which will then render that component (bellow the Navbar, still contained within the app container which contains the background).
Here is some psuedo code of my structure so far (the bad code):
App.js
<div className="App">
<Navigation />
{/* <other components to render here /> */}
</div>
App.css
background-image: url(blah);
background-attachment: fixed;
z-index: -1;
Navigation.js
<Router>
<div className="App-navigation">
<Container>
<Row>
<Link to="/">Home</Link>
<Link to="/About">About Me</Link>
</Row>
</Container>
<Route path="/" exact component={Home} />
<Route path="/About" component={About} />
</div>
</Router>
Navigation.css
.App-navigation {
// blah blah
position: fixed;
z-index: 10;
}
About.js and Home.js just having their respective page content.
With the above, even though Home has more content than the page height, obviously the containing navbar's fixed position prevents scrolling.
I'm pretty new to React, so I'm not sure on the proper procedure in setting up a app routing component, or where it's supposed to fit into the app architecture. Any help or guidance is appreciated!
You simply need to restructure things a bit to ensure that routes/views/components render outside of component Navigation. Move Router to wrap most if not all children of App. Remove the Route elements from Navigation as Route is where the contents of each route/view/component will render. Move the removed Route elements to some other component outside of Navigation and inside Router.
App:
<div className="App">
<Router>
<Navigation />
<Main /> {/* component for rendered components */}
</Router>
</div>
Navigation:
<div className="App-navigation">
<Container>
<Row>
<Link to="/">Home</Link>
<Link to="/About">About Me</Link>
</Row>
</Container>
</div>
Main:
<div className="App-main">
<Container>
<Route path="/" exact component={Home} />
<Route path="/About" component={About} />
</Container>
</div>
Here is an example in action.
Hopefully that helps!
Two quick solutions.
1# Create only 2 components in your Router: app/portfolio and PageNot Found. Lazy load components that you wouldn't want to load immediately. Like About component. The only downside is that url wouldn't change, if you after it.
2# Just import Navbar component in every other page/component or use HOC pattern which basically will grant the same result.

Page to display on start of application

Hello guys and welcome to the next episode of New to React so lets experiment! In this episode we present:
Trying display the Home component on application start.
I went with building the homepage in a different component, not sure if this is the right approach but I thought it would be nice to keep the App.js clean from all the html and such.
Doing this though, causes a problem it seems, as it does not seem to show the Home component on app boot (duh), instead it just displays a black page. In order to get to the hompage you need to click the navbar brand link in the Navigation since I've added a link for that.
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="App">
<Navigation />
<div>
<div>
<h1>Some content</h1>
</div>
<div>
<Route exact path="/" component={Home} />
<Route path="/page1" component={page1} />
<Route path="/page2" component={page2} />
</div>
</div>
<Footer />
</div>
</BrowserRouter>
)
}
}
I think I could use a <Redirect> to redirect to the Home component but this seems like a workaround to me, rather than what should actually happen.
What would be a better way of doing this?

React router works only after refresh

I have problem with react router.
This is my Router:
<Router>
<div>
<Route exact path="/dashboard" component={projetList} />
<Route path="/dashboard/:id" component={
(props) => <Editor documentID={props.match.params.id} />
} />
</div>
</Router>
And Link to:
<Link to="/dashboard">
<button type="button" class="btn btn-outline-success">
</Link>
Problem description:
When I click my element - browser try to go to the http://localhost:3000/dashboard
but the site is blank.
When I refresh my site (F5 button) then my component load.
Also check out this link: Routes are not navigating when React v15.5 setup with react-redux v5 is. And make sure you put the in the right place. Check this for example :
<browserRouter>
https://pastebin.com/M9hU4Bg4

Resources