How to add multiple pages with React & Redux - reactjs

I'm coding a MediumBlog like application and I'm using React & redux and Django Rest Framework for my Backend. I already made the first page, which is the first page you see when you go to https://medium.com/
I'm able to navigate to different categories without refreshing the page, which is the Main Purpose of React. But now, when you want to read a post in the medium blog, the page is refreshing. I have no idea how to do it with react. I know how to build a Single Page App, but here, it seems that a new page is being loaded when you click on a post. My question is :
.Is this loading a new page instead of a new route ( a new HTML file or something )
.How can I handle this " multipage " structure with react
Here is my Single Page App that can load content from different categories
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './css/App.css';
import { Provider } from 'react-redux';
import { store } from '../store.js';
import AppHeader from './header/AppHeader';
import HeaderCategories from './header/HeaderCategories'
import PostListStream from './posts/PostListStream';
import PostList from './posts/PostList';
import { BrowserRouter } from "react-router-dom";
import { Route, Switch } from 'react-router-dom';
class App extends Component {
render(){
return(
<Provider store={store}>
<div className="App">
<AppHeader />
<HeaderCategories />
<Switch>
<Route exact
key="sciences"
path="/sciences"
render={() => <PostListStream field="sciences" />}
/>
<Route exact
key="littérature"
path="/littérature"
render={() => <PostListStream field="littérature" />}
/>
<Route exact
key="sciences-sociales"
path="/sciences-sociales"
render={() => <PostListStream field="sciences-sociales" />}
/>
</Switch>
<PostList />
</div>
</Provider>
)
}
}
ReactDOM.render(<BrowserRouter>
<App />
</BrowserRouter>, document.getElementById('app'));
Here is where my are :
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './css/App.css';
import { Provider } from 'react-redux';
import { store } from '../store.js';
import AppHeader from './header/AppHeader';
import HeaderCategories from './header/HeaderCategories'
import PostListStream from './posts/PostListStream';
import PostList from './posts/PostList';
import { BrowserRouter } from "react-router-dom";
import { Route, Switch } from 'react-router-dom';
class App extends Component {
render(){
return(
<Provider store={store}>
<div className="App">
<AppHeader />
<HeaderCategories />
<Switch>
<Route exact
key="sciences"
path="/sciences"
render={() => <PostListStream field="sciences" />}
/>
<Route exact
key="littérature"
path="/littérature"
render={() => <PostListStream field="littérature" />}
/>
<Route exact
key="sciences-sociales"
path="/sciences-sociales"
render={() => <PostListStream field="sciences-sociales" />}
/>
</Switch>
<PostList />
</div>
</Provider>
)
}
}
ReactDOM.render(<BrowserRouter>
<App />
</BrowserRouter>, document.getElementById('app'));
Thank you so much

You can create dynamic routes to your posts using react-router-dom in a similar way to what you have done with your other routes. react-router doesn't really refresh the page, although it looks like it. It simply renders another component when the route changes.
To create dynamic routes for your posts you can do something like this:
<Route
path="/post/:postId"
render={() => <PostComponent />}
/>
or like this if you want it to be a little more readable:
<Route
path="/post/:postId"
component={PostComponent}
/>
:postId here is a dynamic id, whatever is placed after /post/ in your URL will be considered the postId by react-router.
Inside your PostComponent you can do something like this to fetch your postId variable:
import { withRouter } from "react-router-dom";
const PostComponent = withRouter(props => (
const postId = props.match.params.postId;
return ();
))
You can then use your postId to fetch your post from the backend and do whatever you need to do with it. As soon as you go to your post URL now, it will show the PostComponent without hard refreshing the page.

Related

How to stop random links from opening with react-router?

I am new to React and practicing with an online website for repairing appliances. I have used react-router and created all my routes in a separate file.
I have a problem though, I can open any link from the address bar like:
http://localhost:3000/<randomword>
I only want routes to be opened that I have declared in my routes component while if I type http://localhost:3000/something, I get an empty page with my header and footer in it.
here are my codes:
Index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import Routes from './Routes';
import './index.css';
const App = () => {
return(
<BrowserRouter>
<Routes />
</BrowserRouter>
)
}
ReactDOM.render(<App/>,document.getElementById('root'));
App.js:
import React, {Component} from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import Layout from './Containers/Layout';
import LandingPage from './Containers/Pages/LandingPage';
import About from './Containers/Pages/About';
import Cities from './Containers/Pages/Cities';
import Discount from './Containers/Pages/Discount';
class Routes extends Component {
render(){
return (
<div>
<Layout>
<BrowserRouter>
<Route path="/" render={props => <LandingPage {...props} />} exact component={LandingPage}/>
<Route path="/About" component={About}/>
<Route path="/Cities" component={Cities}/>
<Route path="/Discount" component={Discount}/>
</BrowserRouter>
</Layout>
</div>
);
}
};
export default Routes;
Layout.js:
import React, { Component } from 'react';
import Header from "./Layouts/Header";
import Footer from './Layouts/Footer';
import './Layout.css';
export default class Layout extends Component {
constructor(){
super();
this.state= {
}
}
render() {
return (
<div className="page-container">
<Header/>
<div className="content-wrap">
{this.props.children}
</div>
<Footer/>
</div>);
}
}
Can someone help me figure out how I should stop random random pages to be opened from addressbar?
Just want to start by saying I'm completely self-taught with React so I apologize if this answer is incorrect. However, in my experience with react-router I always have a Switch inside of my BrowserRouter. So your Routes class in app.js should something like this:
class Routes extends Component {
render(){
return (
<div>
<Layout>
<BrowserRouter>
<Switch>
<Route path="/" render={props => <LandingPage {...props} />} exact component={LandingPage}/>
<Route path="/About" component={About}/>
<Route path="/Cities" component={Cities}/>
<Route path="/Discount" component={Discount}/>
</Switch>
</BrowserRouter>
</Layout>
</div>
);
}
};
Just be sure you don't forget to update your imports to
import { Switch, Route, BrowserRouter } from 'react-router-dom';
import { Redirect } from "react-router-dom"
<Route path="/not-found" component={notFound-Component} />
<Redirect to="/not-found" />
This will always redirect you to 404 component if route is not present just make a 404 component and u should add the redirect at the end after all routes are defined

react router 4 switch showing two components

I'm trying to split my routes into many files, to achieve this I have a central file called routes.
import React from "react";
import { Router, Route, Switch } from "react-router-dom";
import history from "./History";
import StreamRoutes from "./stream/StreamRoutes";
const Routes = props => {
return (
<React.Fragment>
<Router history={history}>
<Switch>
<Route path="/" exact component={props => <h1>hello world</h1>} />
<StreamRoutes />
</Switch>
</Router>
</React.Fragment>
);
};
export default Routes;
and then a route file for all the main component like so:
import React from "react";
import { Route } from "react-router-dom";
import StreamCreate from "./components/StreamCreate";
import StreamEdit from "./components/StreamEdit";
import StreamList from "./components/StreamList";
import StreamShow from "./components/StreamShow";
const StreamRoutes = props => {
return (
<React.Fragment>
<Route path="/streams" exact component={StreamList} />
<Route path="/streams/new" exact component={StreamCreate} />
<Route path="/streams/:id" exact component={StreamShow} />
<Route path="/streams/edit/:id" exact component={StreamEdit} />
</React.Fragment>
);
};
export default StreamRoutes;
this works except when I try to access "/streams/new" or "/streams/:id", in any of those cases the router show both components at once.
I would like to know how to fix this or a better way to organize my routes would be highly appreciated.
It is possible to use a regex like FuzzyTree suggest, but this can get messy in a bigger project. I would suggest replacing React.Fragment in your StreamRoutes with Switch. This way it works like you'd expect.

How to properly dynamically change information displayed in a website based on URL?

I'm new to JavaScript and React. I seem to be stuck on this question, I have found information but I think that this is not what I'm really looking for perhaps someone can shed some light on the matter.
So what I'm really looking for is a way to create a "mold" page of an node/react app that will display changing information based on the URL a user submits. Say for example look at facebook (or even stackoverflow) one click on a profile of friends 'y' then the url changes to facebook.com/friends-y and if we choose another person it then changes. Thus I believe that's how they must know how to fill their template using the info provided from that URL with names pictures etc.
I saw that a blog suggests to use route another suggest using url queries more so (which I don't know how to read them once given or how to render them say such as with a onChange event sort of thing when say you click on something inside the page).
My question is: Are any of this methods useful, should I combine them I seen websites that uses both or is there another industry standard that i haven't found and perhaps comes with react?
Any guidance would be much appreciated.
First of all i assume that you have multiple component and you want to change from one component to another component via url. so you have to install react router dom
npm install --save react-router-dom
and after then import Router, Route, Link, Switch (whatever you want) from react-router-dom and give route to component inside router tag .... i mention below in my code
import React, { Component } from 'react';
import './App.css';
import Login from './component/login';
import User from './component/user';
import Signup from './component/signup';
import Notfound from './component/notfound';
import { BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
const Home = () => (
<div>
<h2>Home</h2>
</div>
);
class App extends Component {
constructor(props){
super(props);
this.state={
loggedIn : false
}
}
render() {
return (
<Router>
<div className="App">
<ul className="nav nav-pills">
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/login">LogIn</Link>
</li>
<li>
<Link to="/signup">Sign Up</Link>
</li>
<li>
<Link to="/user">User</Link>
</li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
<Route path="/user" component={User} onEnter={this.requireAuth}/>
<Route path="*" component={Notfound} />
</Switch>
</div>
</Router>
);
}
}
export default App;
note : in my code i have total 5 component in my project
Login,
User,
Signup,
NotFound,
Home
for more router information you can check in this site. https://reacttraining.com/react-router/web/example/basic
import React , {Component} from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import App from './Components/Home/App'
import Digital from './Components/DigitalStrat/Digital-Strat';
import ServiceLines from './Components/Serviceline/ServiceLines';
import Operations from './Components/OperationTransformation/Operations-
Transformation';
import WhyUs from './Components/WhyUs/Why-us';
import Mission from './Components/Mission/Mission';
import OurGroup from './Components/OurGroup/OurGroup';
import Team from './Components/Team/Team';
import Projects from './Components/Projects/Projects';
import Research from './Components/Research/Research';
import News from './Components/News/News';
import Locations from './Components/Location/Locations';
import registerServiceWorker from './registerServiceWorker';
import NewsDetails from "./Components/NewsDetails/newsDetails";
import i18n from './js/i18n'
import { sliderArrow } from './js/sliderArrow';
import { menu } from './js/menu';
import {withRouter} from 'react-router';
import Coockies from './Components/Cookies/Cookies';
class ScrollToTop extends Component {
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
window.scrollTo(0, 0)
}
}
render() {
return this.props.children
}
}
export default withRouter(ScrollToTop);
ReactDOM.render(
<BrowserRouter>
<Switch>
<ScrollToTop>
<Route exact path = "/" component = {App} />
<Route exact path='/index.html' component={App}/>
<Route exact path='/Digital-Strategies.html' component={Digital} />
<Route exact path='/Service-Lines.html' component={ServiceLines} />
<Route exact path='/Operations-Transformation.html' component=
{Operations}/>
<Route exact path='/inside-the-company.html' component={WhyUs}/>
<Route exact path='/Mission.html' component={Mission}/>
<Route exact path='/Our-group.html' component={OurGroup}/>
<Route exact path='/Team.html' component={Team}/>
<Route exact path='/Projects.html' component={Projects}/>
<Route exact path ='/Research-Development.html' component = {Research}/>
<Route exact path='/News.html' component={News}/>
<Route exact path='/news-details.html/:slug' component={NewsDetails}/>
<Route exact path='/Locations.html' component={Locations}/>
<Route exact path='/cookies' component={Coockies} />
</ScrollToTop>
</Switch>
</BrowserRouter>, document.getElementById('root'));
registerServiceWorker();
This is the basic way to route the project. Feel free to ask question.
The way to handle routing in React is with React Router.
With this sort of (virtual) routing there are two main ways that routing needs to be handled.
1. The first is by rendering different components when the url changes—for example rendering a <Home/> component for "/" and an <About/> component for "/about".
An example:
import React, { Component } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import Home from "./pages/Home";
import About from "./pages/About";
class App extends Component {
render() {
return (
<Switch>
<Route exact path="/" component={ Home }/>
<Route path="/about" component={ About }/>
</Switch>
)
}
}
export default withRouter(App);
2. The second case, which I believe your question specifically addresses, is rendering the same component with different data depending on the url—for example having a <Profile/> component but changing its data for "/profiles/1" vs "/profiles/2".
An example:
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class Profile extends Component {
constructor() {
super();
this.state = {
profileData: {}
}
}
componentDidMount() {
this.fetchData();
}
componentDidUpdate(prevProps) {
const currentId = this.props.match.params.id;
const prevId = prevProps.match.params.id;
if (currentId !== prevId) {
this.fetchData();
}
}
async fetchData() {
const profileId = this.props.match.params.id;
const profileData = await fetch(`http://example.com/api/profiles/${profileId}`);
this.setState({
profileData
});
}
render() {
const { profileData } = this.state;
return (
<div>
<h1>{ profileData.name }</h1>
</div>
)
}
}
export default withRouter(Profile);
Where the containing parent component of <Profile/> has a <Route/> that looks like this:
<Route path="/profiles/:id" component={ Profile }/>
Which is important so that the id is in this.props.match.params.
Note that in the above example the way to check what data to use to populate the view is by checking the :id parameter in the url. Since information about the url is passed to the <Profile/> component as a prop, we can check if the url changes in componentDidUpdate and get new data if there was a change.
Finally, both of these involve a bit of setup with React Router (basically just wrapping your <App/> in a <Router/>) but the documentation should help with that: https://reacttraining.com/react-router/web/guides/quick-start.
Hopefully this helps.

Component not rendering in React Router multi step form

so im using react router and formik to create a multi step form. ive based my booking application on this article.
https://codedaily.io/tutorials/50/Create-a-Form-Wizard-with-Data-Loss-Prevention-using-Formik-and-React-Router
ive got the basic routing down. Im just trying to redirect the user to Section 1 of my booking form when they land on the /make-a-booking url. its pretty simple but im not sure if im missing something. So the issue im having is that the ContactSection isnt rendering anything. Is it possible to create a multi step form with just formik?
Here is the link to the githib repo.
https://github.com/umxr/booking-form
Here is the code for the App.js
import React, { Component } from 'react';
import FormWizard from './components/FormWizard';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import About from './components/About';
import Contact from './components/Contact';
import Home from './components/Home';
class App extends Component {
render() {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/make-a-booking" component={FormWizard} />
<Route exact path="/about" component={About} />
<Route exact path="/contact" component={Contact} />
</Switch>
</Router>
</div>
);
}
}
export default App;
Here is the code for the FormWizard.js
import React, { Component } from 'react';
import Layout from './Layout';
import { BrowserRouter as Router, Switch, Route, Redirect } from "react-router-dom";
import { Formik, Form } from "formik";
import ContactSection from './sections/ContactSection';
import PhoneSection from './sections/PhoneSection';
class FormWizard extends Component {
render() {
return (
<Layout>
<Switch>
<Redirect from="/make-a-booking" to="/make-a-booking/contact" />
<Route exact path="/make-a-booking/contact" component={ContactSection} />
<Route exact path="/make-a-booking/phone" component={PhoneSection} />
</Switch>
</Layout>
)
}
}
export default FormWizard;
the contactSection and PhoneSection currently just render out a string along the lines of 'this is the phone section' etc

React Router is not rendering component while using electron

I am trying to develop a Desktop app using Electron + React. I am using electron-react-boilerplate.
I have defined my route in the routes.js and referred to the component and yet in development it fails to render the page when I click on it.
routes.js
import React from 'react';
import { HashRouter as Router } from 'react-router-dom';
import { Switch, Route } from 'react-router';
import App from './containers/App';
import HomePage from './containers/HomePage';
import PersonFind from './containers/PersonFind';
export default () => (
<Router>
<App>
<Switch>
<Route path="/" component={HomePage} />
<Route path="/identify" component={PersonFind} />
</Switch>
</App>
</Router>
);
PersonFind.js
import React, { Component } from 'react';
import Header from '../components/Header';
class PersonFind extends Component {
render() {
return (
<div>
<Header />
<h1> Works </h1>
</div>
);
}
}
export default PersonFind;
Use exact in your index route.
<Route exact path="/" component={HomePage} />
/identify match with both / and /identify. Since these two routes are inside a <Switch>, only first one (HomePage) get rendered.

Resources