React - URL gets updated but the page is not rendered - javascript

I am following along a beginner's course on React. The Nav. Bar has two options - About, HomePage. On clicking on the bar, the url gets updated but the page remains the same and nav stays. I get no error.
App.js
import React from 'react';
import HomePage from './HomePage';
import About from './About';
import Header from './common/Header';
function App() {
function getPage() {
const route = window.location.pathname;
if (route === "about") return <About />;
console.log("hi");
return <HomePage />;
}
return(
<div className="container-fluid">
<Header>
{ getPage() }
</Header>
</div>
);
}
export default App;
Header.js
import React from 'react';
//to navigate across the website
function Header(){
return (
<nav>
Home | About
</nav>
);
}
export default Header;
index.js
import "bootstrap/dist/css/bootstrap.min.css";
import React from "react";
import {render} from "react-dom";
import App from "./components/App";
render(<App />, document.getElementById("root"));
About.js
import React from 'react';
class About extends React.Component{
render (){
return(
<>
<h1> About </h1>
<p> This is the About Page </p>
</>
);
}
}
export default About;
HomePage.js
import React from "react";
import 'bootstrap/dist/css/bootstrap.min.css';
function HomePage(){
return(
<div className="jumbotron">
<h1>
Welcome
</h1>
<p>
This is my first React Project
</p>
</div>
);
}
export default HomePage;
There is no change in the page, only the URL gets updated.
I have tried many solutions on SO but none worked so far.

I'm guessing it always displays the <HomePage /> component?
That's because window.location.pathname returns a path with a leading slash. So route === "about" will always be false. You need to check route === "/about" instead.

In getPage function condition is wrong it's not about it's will be /about
Just change condition in if statement
like this
if (route === "/about") return <About />;

Related

How to render my home component in the app.js file?

I am trying to render my home component in the App.js like this: export function App() { return ( < Home /> ) }
but It does not display my content. Why is that?
I am not receiving any errors.
You can import and call the component like I have mentioned below,
App.js
import './App.css';
import Home from './Components/Home'
function App() {
return (
<div className="App">
<Home />
</div>
);
}
export default App;

TypeError: this.props.location.state is undefined -

I have a little problem with my application developed in ReactJS.
Here are my components App.js, AppFront.js and index.js.
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.scss';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>,
document.getElementById('root')
);
serviceWorker.unregister();
App.js
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import AppFront from './AppFront';
import WizardList from './wizard/WizardList';
import './App.scss';
function App() {
return (
<div className="App">
<Switch>
<Route exact path="/" component={AppFront} />
<Route path="/wizard/:id" component={WizardList} />
</Switch>
</div>
);
}
export default App;
AppFront.js
import React from 'react';
import Wizard from './wizard/Wizard';
function AppFront() {
return (
<div className="AppFront">
<Wizard />
</div>
);
}
export default AppFront;
In the application, I have a "Wizard" folder in which are included the components "dataWizard.js", "Wizard.jsx" and "WizardList.jsx"
folder-structure
The "dataWizard.js" file contains an array of objects.
export const dataWizard = [
{
id: "1",
name: "Harry Potter",
category: "Gryffondor",
text: "Harry is a powerful wizard."
},
{
id: "2",
name: "Drago Malefoy",
category: "Serpentard",
text: "Draco Malfoy is not very brave."
}
The "Wizard.jsx" component loops on this table and transmits the properties with the component of "react-router-dom".
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { dataWizard } from './dataWizard';
import './style/Wizard.scss';
class Wizard extends Component {
render() {
return (
<div className="Wizard">
{
dataWizard.map((wizard, i) =>
<Link
to={{ pathname: `/wizard/${wizard.id}`, state: { wizard } }}
key={i}
>
<span className="name">{wizard.name}</span>
<span className="category">{wizard.category}</span>
</Link>
)
}
</div>
);
}
}
export default Wizard;
I recover the properties without problem with the component "WizardList.jsx".
import React, { Component } from 'react';
import './style/WizardList.scss';
class Wizard extends Component {
render() {
const wizard = this.props.location.state.wizard;
return (
<div className="WizardList">
<div className="container">
<span className="name">{wizard.name}</span>
<span className="category">{wizard.category}</span>
<span className="text">{wizard.text}</span>
</div>
</div>
);
}
}
export default Wizard;
Only when I reload the page, or try to access it directly by typing the path in the URL bar, an error message appears and this.props.location.state is undefined.
Here are some pictures in progressive order to help you better understand my problem.
Homepage - number 1
Information about sorcerer after click - number 2
I am trying to go directly to the informative page on the sorcerer. - number 3
Error message - number 4
Please, I am a beginner, and I have tried several methods seen on the web, but I still cannot resolve this problem. Please, help-me! :)
WizardList gets the data to load from the location.state you are sending it in this Link
<Link
to={{ pathname: `/wizard/${wizard.id}`, state: { wizard } }}
key={i}
>
...but if you refresh in /wizard/:id you have nothing in location.state because you have not followed a link.
However, you have the id of the wizard in the link so you can access it with this.props.match.params.id. Then if there's something in location.state you can use it to load the page but if not, you can take the wizard id and find the proper wizard of the list.
import React, { Component } from 'react';
import { dataWizard } from './dataWizard';
import './style/WizardList.scss';
class Wizard extends Component {
render() {
const wizard = this.props.location ? this.props.location.state.wizard : dataWizard.find(wizard => wizard.id === this.props.match.params.id);
return (
<div className="WizardList">
<div className="container">
<span className="name">{wizard.name}</span>
<span className="category">{wizard.category}</span>
<span className="text">{wizard.text}</span>
</div>
</div>
);
}
}
export default Wizard;

Redirect to a static html page in react.js

I am learning React, so this question may make no sense but I want to learn it.
I have index.html page and I want to jump to Components.html page.
RouteToComponent.jsx
import React from 'react';
class RouteToComponents extends React.Component {
render() {
return (
<div>
Components
</div>
);
}
}
export default RouteToComponents;
RouteToComponent.jsx is called inside index.jsx
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import RouteToComponents from './BasicJSX/RouteToComponents.jsx';
class App extends React.Component {
render() {
return (
<div>
Hello World!!!
<RouteToComponents />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
export default App;
components.jsx
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return (
<div>
Entered Components HTML!!!
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
export default App;
But when I click on a tag URL changes but the page remains same.
Wrap your App.js with Router and define Routes. <Route /> allows us to define all paths of our Application.
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import RouteToComponents from './RouteToComponents.jsx';
import AnyComponent from './AnyComponent';
import App from './App.jsx';
return (
<Router>
<RouteToComponents />
<Switch>
<Route exact path="/" component={App} />
<Route path="/Components/Components.html" component={AnyComponent} />
</Switch>
</Router>
);
Now in your Component where you want to use Link.
In React <Link /> is used instead of anchor.
import { Link } from "react-router-dom";
return (
<div>
<Link to="Components/Components.html">Components</Link>
<Link to="/">Home</Link>
</div>
);
to in Link attribute is similar to href in anchor.
Remember:
npm i react-router-dom
to attribute of Link must be similar to the path defined in App.js Route.
Because when you click on Link it matches Routes in App.js

Redirecting using React Router shows blank page

I'm trying to build a simple example project where the user is redirected to the 'contact' page upon clicking a button, using React. I'm trying to achieve this by setting the value of a state property. When I run the code I have, it does change the browser address bar URL to that of the contact page, but does not seem to actually load the component - I get a blank page instead. If I manually navigate to that URL (http://localhost:3000/contact) I can see the contents.
Here are my App.js and Contact.js files -
App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, Redirect } from 'react-router-dom';
import Contact from './Contact';
class App extends Component {
state = {
redirect: false
}
setRedirect = () => {
this.setState({
redirect: true
})
}
renderRedirect = () => {
if (this.state.redirect) {
return <Redirect to='/contact' />
}
}
render() {
return (
<Router>
<Switch>
<Route exact path='/contact' component={Contact} />
</Switch>
<div>
{this.renderRedirect()}
<button onClick={this.setRedirect}>Redirect</button>
</div>
</Router>
)
}
}
export default App;
Contact.js
import React, { Component } from 'react';
class Contact extends Component {
render() {
return (
<div>
<h2>Contact Me</h2>
<input type="text"></input>
</div>
);
}
}
export default Contact;
Using state isn't really a requirement for me, so other (preferably simpler) methods of redirection would be appreciated too.
Since your button is nothing more than a link, you could replace it with:
<Link to="/contact">Redirect</Link>
There are many alternatives though, you could for example look into BrowserRouter's browserHistory:
import { browserHistory } from 'react-router'
browserHistory.push("/contact")
Or perhaps this.props.history.push("/contact").
There are pros and cons to every method, you'll have to look into each and see which you prefer.
I got here for a similiar situation. It's possible use withRouter (https://reactrouter.com/web/api/withRouter) to handle that.
This example was tested with "react": "^16.13.1","react-router-dom": "^5.2.0" and "history": "^5.0.0" into "dependecies" sections in package.json file.
In App.js I have the BrowserRouter (usually people import BrowserRouter as Router, I prefer work with original names) with Home and Contact.
App.js
import React, { Component } from "react";
import {
BrowserRouter,
Switch,
Route,
} from "react-router-dom";
import Home from "./pages/Home";
import Contact from "./pages/Contact";
class App extends Component
{
// stuff...
render()
{
return (
<BrowserRouter>
<Switch>
<Route path="/contact">
<Contact />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</BrowserRouter>
);
}
}
export default App;
ASIDE 1: The Route with path="/contact" is placed before path="/" because Switch render the first match, so put Home at the end. If you have path="/something" and path="/something/:id" place the more specific route (with /:id in this case) before. (https://reactrouter.com/web/api/Switch)
ASIDE 2: I'm using class component but I believe (I didn't test it) a functional component will also work.
In Home.js and Contact.js I use withRouter associated with export keyword. This makes Home and Contact components receive the history object of BrowserRouter via props. Use method push() to add "/contact" and "/" to the history stack. (https://reactrouter.com/web/api/history).
Home.js
import React from "react";
import {
withRouter
} from "react-router-dom";
export const Home = ( props ) =>
{
return (
<div>
Home!
<button
onClick={ () => props.history.push( "/contact" ) }
>
Get in Touch
<button>
</div>
);
}
export default withRouter( Home );
Contact.js
import React from "react";
import {
withRouter
} from "react-router-dom";
export const Contact = ( props ) =>
{
return (
<div>
Contact!
<button
onClick={ () => props.history.push( "/" ) }
>
Go Home
<button>
</div>
);
}
export default withRouter( Contact );
Particularly, I'm using also in a BackButton component with goBack() to navigate backwards:
BackButton.js
import React from "react";
import {
withRouter
} from "react-router-dom";
export const BackButton = ( props ) =>
{
return (
<button
onClick={ () => props.history.goBack() }
>
Go back
<button>
);
}
export default withRouter( BackButton );
So I could modify the Contact to:
Contact.js (with BackButton)
import React from "react";
import BackButton from "../components/BackButton";
export const Contact = ( props ) =>
{
return (
<div>
Contact!
<BackButton />
</div>
);
}
export default Contact; // now I'm not using history in this file.
// the navigation responsability is inside BackButton component.
Above was the best solution for me. Other possible solutions are:
useHistory Hook (https://reactrouter.com/web/api/Hooks)
work with Router instead BrowserRouter - (https://reactrouter.com/web/api/Router)

React Router Link changes path, but doesn't render new component

I'm trying to use React Router 4.2.2 in order to load a component called PostFocus whenever I click on a 'Card' component, with a Link wrapped around it. When I click on a 'Card' the path changes correctly, but the PostFocus component isn't rendered. Have I done something wrong or missed something out in the Route? I can't figure it out.
Here is the code:
class PostsList extends React.Component {
render() {
var createCards = this.props.posts.map((post, i) => {
return (
<div key={i}>
<Link to={`/${post.id}`}>
<Card title={post.title} subtitle={post.subtitle} date={post.date} id={post.id}/>
</Link>
<Route exact path={`/${post.id}`} render={(post) => (
<PostFocus content={post.content}/>
)}/>
</div>
);
});
return (
<div>
{createCards}
</div>
);
}
App Component:
import React from 'react';
import PostsList from '../containers/posts_list.js';
import {withRouter} from 'react-router';
class App extends React.Component {
render() {
return(
<div>
<PostsList />
</div>
);
}
}
export default withRouter(App);
index.js code:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import { BrowserRouter } from 'react-router-dom';
import App from './components/App.jsx';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
, document.getElementById('root'));
I was also facing the same problem. I fixed it with a trick.
You might have BrowseRouter in your App.js or index.js, I had it in my index.js like this :
ReactDOM.render(<BrowserRouter>
<App />
</BrowserRouter>, document.getElementById('root'))
I changed it to :-
ReactDOM.render((
<BrowserRouter>
<Route component={App} />
</BrowserRouter>
), document.getElementById('root'))
and it tricked, actually we are keeping the router look over our complete application by doing this, thus it also checks up with the routing path and automatically renders the view. I hope it helps.
Note:- Do not forget to import Route in your index.js
#Tom Karnaski
Hi... Sorry for the late reply, I was not getting time to work on it.. Your code is running in my system, I didn't had access to push a branch in your repo.. make your App.js like below.. it will work for sure..
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Navbar from './Components/Navbar/Navbar';
class App extends React.Component {
render() {
return (
<Router>
<div className="App">
<Route component={Navbar}/>
</div>
</Router>
);
}
}
export default App;
I solved this problem simply use tag instead of Link helper. Not sure is it right or not, but it works for me, hope it will helps anybody else.

Categories

Resources