Why React Router only works with stateless component? - javascript

I'm trying the simplest code to understand the React Router.
I brought the example of the site: "https://reacttraining.com/react-router/web/example/basic" and only changed one thing, the component 'About'.
import React from 'react'
import ReactDOM from 'react-dom'
import registerServiceWorker from './registerServiceWorker'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about/:aaa" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
class About extends React.Component {
render() {
return (
<div>
<h2>About</h2>
</div>
);
}
}
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
console.log('Topics', Topics);
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
export default BasicExample
ReactDOM.render(<BasicExample />, document.getElementById('root'));
registerServiceWorker();
If i use:
class About extends React.Component {
render() {
return (
<div>
<h2>About</h2>
</div>
);
}
}
React-router do not show this component. and why i want to use this? because with this i can use State.
Now i'm reading this article: https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc
Maybe i will find the answer there. then i will come and edit...

Related

onclick of sidebar item issue in react

i am trying to create a simple react project. it has a navbar, sidebar and the main content area.
first a home component is displayed.
home.js
import { useState } from "react";
import Navbar from "../navbar/navbar";
import Sidebar from "../sidebar/sidebar";
import "./style.css";
import { useSelector, useDispatch } from 'react-redux'
function Home() {
const sidebarOpen = useSelector((state) => state.sidebarOpenState);
return (
<>
<Navbar />
<div className="home-box d-flex">
{sidebarOpen && <div className="p-2 flex-fill"><Sidebar /></div>}
</div>
</>
);
}
export default Home;
my navbar has a button which will change state sidebarOpen.
my sidebar looks like this->
sidebar.js
import "./style.css";
import { Link } from "react-router-dom";
function Sidebar() {
return (
<div className="divSidebar">
<ul>
<li>
<Link to="/chess">
<img className="sidebar-img" src="images/sidebar/chess.png"></img>
<span className="sidebar-text">Chess</span>
</Link>
</li>
<li>
<Link to="/volleyball">
<img
className="sidebar-img"
src="images/sidebar/volleyball.png"
></img>
<span className="sidebar-text">Volleyball</span>
</Link>
</li>
<li>
<Link to="/football">
<img
className="sidebar-img"
src="images/sidebar/football.png"
></img>
<span className="sidebar-text">Football</span>
</Link>
</li>
<li>
<Link to="/tabletennis">
<img
className="sidebar-img"
src="images/sidebar/table-tennis.png"
></img>
<span className="sidebar-text">TableTennis</span>
</Link>
</li>
<li>
<Link to="/rugby">
<img className="sidebar-img" src="images/sidebar/rugby.png"></img>
<span className="sidebar-text">Rugby</span>
</Link>
</li>
</ul>
</div>
);
}
export default Sidebar;
when i click on chess, the respective component should be loaded.
chess.js
function Chess() {
return (
<>
<h1>chess</h1>
</>
);
}
export default Chess;
but the problem is my sidebar disappears. i only want the main content area to be changed nothing else. can someone help? let me know if u want to some more code.
---------edit
i have added console.log in two places. one is in the navbar where the toggle method is defined and another is in redux store where toggle state is defined. both the places onclick is working. i am able to see message but the sidebar is not getting rendered.
---------edit 2
App.js
import "./App.css";
import Navbar from "./components/navbar/navbar";
import { Route, Routes } from "react-router-dom";
import Chess from "./components/chess/chess";
import Volleyball from "./components/volleyball/volleyball";
import Football from "./components/football/football";
import TableTennis from "./components/tabletennis/tabletennis";
import Rugby from "./components/rugby/rugby";
import Home from "./components/home/home";
function App() {
return (
<div className="App">
<Routes>
<Route exact path="/" element={<Home />} />
<Route
path="/chess"
element={
<>
<Navbar />
<Chess />
</>
}
/>
<Route
path="/volleyball"
element={
<>
<Navbar />
<Volleyball />
</>
}
/>
<Route
path="/tabletennis"
element={
<>
<Navbar />
<TableTennis />
</>
}
/>
<Route
path="/football"
element={
<>
<Navbar />
<Football />
</>
}
/>
<Route
path="/rugby"
element={
<>
<Navbar />
<Rugby />
</>
}
/>
</Routes>
</div>
);
}
export default App;
When you click on Chess you navigate to "/chess"
So if u can't see your Navbar there, is because you have to render it there too.
Or, render the Navbar outside de Routes from BrowsterRouter.
We need to see the components rendering on "/chess" and the react-router-dom config on app.js (or on the top lvl you declare it)
----- edit ------
Ok, look this:
function App() {
return (
<BrowserRouter>
<NavBar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/test" element={<Test />} />
</Routes>
</BrowserRouter>
);
}
If you refactor your brower like this is gona be more clean to understand the code and even easy to escale.
As u see, the navBar is outside the Routes, so its gona be visible in all routes.
then you can have this:
-> one path -> one element
your Links on navbar (or sidebar or whatelse) are gona work good.
i found a way. i rendered <Sidebar /> again in all my child components.
like this->
chess.js
function Chess() {
const sidebarOpen = useSelector((state) => state.sidebarOpenState);
return (
{sidebarOpen && (
<div className="p-2 flex-fill">
<Sidebar />
</div>
)}
)
}
this way when i click on button the state is updated and sidebar is rendered automatically.

React Router Props of parent component refresh whenever I switch between children components

I am trying to create simple social media app using React, where users would post something and everyone else would see posts on feed.
I have a Home component, to whom I pass props through login component using useHistory.push method.
In Home component I want NavBar to be persistent and to switch content using NavBar links. Whenever I change child component using Route and Link, Home component reloads and loses props, leading to 'cant read property username of undefined' error.
In props I only keep username of logged person.
App component (default)
function App() {
console.log('app loaded')
return (
<BrowserRouter>
<Route path="/" exact component={Login} />
<Route path="/app" component={Home} />
<Route path="/register" exact component={Register} />
</BrowserRouter>
);
}
export default App;
Home component
const Home = (props) => {
console.log('loaded home')
const username = props.location.state.username
return (
<div>
<NavBar user={username} />
<Switch>
<Route path="/app/feed" component={Feed} />
</Switch>
</div>
)
}
export default Home;
NavBar component
const NavBar = (props) => {
return (
<nav className="navbar navbar-expand-md navbar-light fixed-top">
<h2>Welcome, {props.user}</h2>
<ul className="navbar-nav">
<li className="nav-item">
<Link to="/app/feed" className="nav-link">Feed</Link>
</li>
<li className="nav-item">
<Link to="/app" className="nav-link">User Page</Link>
</li>
<li className="nav-item">
<Link to="/" className="nav-link" id="log-out-link">Log out</Link>
</li>
</ul>
</nav>
)
}
export default NavBar;
I've just begun using React, so if I need different approach I'd be grateful to read some advices.
Ciao, I would rewrite your code like this:
App.js
function App() {
console.log('app loaded')
return (
<BrowserRouter>
<Route path="/" exact component={Login} />
<Route path="/app" component={Home}>
<Route path="/app/feed" component={Feed} />
</Route>
<Route path="/register" exact component={Register} />
</BrowserRouter>
);
}
export default App;
Home.js
const Home = (props) => {
console.log('loaded home')
const username = props.location.state.username
return (
<div>
<NavBar user={username} />
</div>
)
}
export default Home;
NavBar.js
const NavBar = (props) => {
return (
<nav className="navbar navbar-expand-md navbar-light fixed-top">
<h2>Welcome, {props.user}</h2>
<ul className="navbar-nav">
<li className="nav-item" onClick={() => history.push('/app/feed') }>
</li>
<li className="nav-item" onClick={() => history.push('/app') }>
</li>
<li className="nav-item" onClick={() => history.push('/')>
</li>
</ul>
</nav>
)
}
export default NavBar;
This implementation should solve your problem.

React Routing: URL is changing but page is not loading

In React(v16.13.1), The URL is changing but page is not loading.
I found the similar questions ReactJS - React Router not changing component but url is changing
and React Router URL Change but Not Component in stack and i tried from different ways but none helps me.
It may be a small mistake, Please help to rectify this.
My code follows:
App.js file
import React, { Component } from "react";
import { BrowserRouter as Router, Route,Switch,Redirect } from "react-router-dom";
import TopNav from "./components/Navbar/TopNav";
import SideNav from "./components/Navbar/SideNav";
import Dashboard from "./components/Dashboard";
import Analytics from "./components/Analytics";
import ToDo from "./components/ToDo";
class App extends React.Component {
render() {
return (
<div>
<TopNav />
<SideNav />
<Router>
<Switch>
<Route exact path="/">
<Dashboard />
</Route>
<Route exact path="/analytics">
<Analytics />
</Route>
{/* <Route exact path="/analytics" component={Analytics}></Route> */}
<Route exact path="/todo">
<ToDo />
</Route>
<Redirect to="/"></Redirect>
</Switch>
</Router>
</div>
);
}
}
export default App;
SideNav.js page as follows:
import React from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
class SideNav extends React.Component {
render() {
return (
<div className="sidebar-wrapper">
<div className="sidebar-container">
<Router>
<ul className="sidebar-menu">
<li className="active">
<i className="fa fa-cubes"></i>
<Link className="link" to="/">
Dashboard
</Link>
</li>
<li>
<i className="fa fa-pie-chart"></i>
<Link className="link" to="/analytics">
Analytics
</Link>
</li>
<li>
<i className="fa fa-medkit"></i>
<Link className="link" to="/todo">
What to do?
</Link>
</li>
</ul>
</Router>
</div>
</div>
);
}
}
export default SideNav;
Thanks in advance!
You only need one <Router> at top level of your app.
You are already using <Router> in your App component.
Wrap the SideNav component in the Router and remove the Router used in SideNav.
import React, { Component } from "react";
import {
BrowserRouter as Router,
Route,
Switch,
Redirect,
Link
} from "react-router-dom";
class SideNav extends Component {
render() {
return (
<div className="sidebar-wrapper">
<div className="sidebar-container">
{/* <Router> */}
<ul className="sidebar-menu">
<li className="active">
<i className="fa fa-cubes" />
<Link className="link" to="/">
Dashboard
</Link>
</li>
<li>
<i className="fa fa-pie-chart" />
<Link className="link" to="/analytics">
Analytics
</Link>
</li>
<li>
<i className="fa fa-medkit" />
<Link className="link" to="/todo">
What to do?
</Link>
</li>
</ul>
{/* </Router> */}
</div>
</div>
);
}
}
class App extends Component {
render() {
return (
<div>
<Router>
<SideNav />
<Switch>
<Route exact path="/">
<div>/</div>
</Route>
<Route exact path="/analytics">
<div>ana</div>
</Route>
<Route exact path="/todo">
<div>todo</div>
</Route>
<Redirect to="/" />
</Switch>
</Router>
</div>
);
}
}
export default App;
Your <SideNav /> and the main content are in seperate <Router />s. They don't see each other, and they can't work together.
Think, like two iframes navigaing independantly of each other, just without the actual iframes.
Everything that reqiures the router, basically your entire app, needs to be inside a single <Router />.
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import TopNav from "./components/Navbar/TopNav";
import SideNav from "./components/Navbar/SideNav";
import Dashboard from "./components/Dashboard";
import Analytics from "./components/Analytics";
import ToDo from "./components/ToDo";
class App extends React.Component {
render() {
return (
<Router>
<TopNav />
<SideNav />
<Switch>
<Route exact path="/">
<Dashboard />
</Route>
<Route exact path="/analytics">
<Analytics />
</Route>
{/* <Route exact path="/analytics" component={Analytics}></Route> */}
<Route exact path="/todo">
<ToDo />
</Route>
<Redirect to="/"></Redirect>
</Switch>
</Router>
);
}
}
export default App;
SideNav.js
import React from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
class SideNav extends React.Component {
render() {
return (
<div className="sidebar-wrapper">
<div className="sidebar-container">
<ul className="sidebar-menu">
<li className="active">
<i className="fa fa-cubes"></i>
<Link className="link" to="/">
Dashboard
</Link>
</li>
<li>
<i className="fa fa-pie-chart"></i>
<Link className="link" to="/analytics">
Analytics
</Link>
</li>
<li>
<i className="fa fa-medkit"></i>
<Link className="link" to="/todo">
What to do?
</Link>
</li>
</ul>
</div>
</div>
);
}
}
The same applies for the TopNav.js.

Read data about specific element in a list

I have this list:
render() {
return (
<section className='display-question'>
<div className='wrapper'>
<ul style={{listStyleType: 'none'}}>
{/*kategoria, poziom (liceum itd), pkty, zdjecie*/}
{this.state.questions.map((question) => {
return (
<li key={question.id}>
<h3>Kategoria: {question.category}</h3>
<p>Poziom: {question.level}</p>
<p>Punkty: {question.pointAmount}</p>
<img alt='' style={{width: '20%'}} src={question.photoURL}/>
<Button onClick={this.clickHandler} style={{display: 'block', margin: 'auto'}}
bsStyle="primary" id={question.id}>Rozwiaz to zadanie kurwo
</Button>
</li>
)
})}
</ul>
</div>
</section>
)
}
I want, every time someone clicks on the button, it will take them to a different screen, showing more details. But I have no idea how to start. So far this is my App.js
import React, {Component} from 'react';
// import logo from './logo.svg';
import './App.css';
import Navbar from "./components/nav";
import Questions from './components/questions';
import {Stuff} from './components/stuff';
class App extends Component {
constructor(p) {
super(p);
this.state = {user: null};
this.checkUserState = this.checkUserState.bind(this);
}
checkUserState(user) {
this.setState({user});
}
render() {
return (
<div className="App">
<Navbar {...this}/>
{this.state.user ? <Questions/> : <Stuff/>}
</div>
);
}
}
export default App;
And this is the Questions.js file:
import React from 'react';
import firebase from 'firebase';
import {Button} from 'react-bootstrap';
class Questions extends React.Component {
constructor(props) {
super(props);
this.state = {
currentItem: '',
username: '',
questions: []
}
this.clickHandler = this.clickHandler.bind(this);
}
componentDidMount() {
const questionsRef = firebase.database().ref('Works');
questionsRef.on('value', (snapshot) => {
let questions = snapshot.val();
let newState = [];
for (let question in questions) {
newState.push({
id: question,
category: questions[question].category,
level: questions[question].level,
pointAmount: questions[question].pointAmount,
photoURL: questions[question].photoURL,
});
}
this.setState({
questions: newState
});
});
}
clickHandler() {
console.log("e");
}
render() {
return (
<section className='display-question'>
<div className='wrapper'>
<ul style={{listStyleType: 'none'}}>
{/*kategoria, poziom (liceum itd), pkty, zdjecie*/}
{this.state.questions.map((question) => {
return (
<li key={question.id}>
<h3>Kategoria: {question.category}</h3>
<p>Poziom: {question.level}</p>
<p>Punkty: {question.pointAmount}</p>
<img alt='' style={{width: '20%'}} src={question.photoURL}/>
<Button onClick={this.clickHandler} style={{display: 'block', margin: 'auto'}}
bsStyle="primary" id={question.id}>Rozwiaz to zadanie kurwo
</Button>
</li>
)
})}
</ul>
</div>
</section>
)
}
}
export default Questions;
And this is what I have for the question.js file.
import React from 'react';
export default class Question extends React.Component {
constructor(p) {
super(p);
}
render() {
return (
<React.Fragment>
<img src="" alt=""/>
</React.Fragment>
)
}
}
So how this works: I grab the list from Firebase, then I render a list with h3, some ps, img, and a button.
I want when the button is clicked, for the user to be taken to a different "screen" with more details. But I cannot see how to set it up.
Any help will be appreciated. I'm open to another suggestions. I was thinking about making it a modal, but this doesn't seem right.
The missing piece is that you don't use any routing library.
The most popular one is react-router.
Here's a basic example (from their docs), that will help you to understand the idea and help you start using it:
import React from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.path}/:topicId`} component={Topic}/>
<Route exact path={match.path} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
export default BasicExample

routing trouble while running in reactjs

I was trying to do a project unfortunetly the router doesn't works.. Please give your kind glance of view to my code.. Can anyone gets whats the correct issue of my code.. here is my code..
routes.js page
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { LoginForm } from './components/LoginForm/LoginForm';
import { About } from './components/About/About';
import { Companies } from './components/Companies/Companies';
import { HomePage } from './components/HomePage/HomePage';
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
class Routes extends Component {
componentDidMount(){
alert("ok");
}
render() {
return (
<div>
<Router>
<Switch>
<Route path="/" component={HomePage}/>
<Route path="/about" component={About}/>
<Route path="/loginform" component={LoginForm}/>
<Route path="/companies" component={Companies}/>
</Switch>
</Router>
</div>
);
}
}
export default Routes;
& this is my homepage.js
class HomePage extends Component {
componentDidMount(){
alert("hme");
}
render() {
return (
<div className="backgrnd" >
<h1><blink> MULTIHAND ONLINE IT WORLD</blink></h1>
<h3 className="outside"><marquee>It's First Time In India.. New Evolution Rising Up.. Your Complete Business,Carrier & Developing Partner..</marquee></h3>
<Router>
<div className="banner">
<div>
<ul>
<li><Link className="a" to='/'>•Home</Link></li>
<li><Link className="a" to='/about'>•About</Link></li>
<li><Link className="a" to='/loginform'>•Login</Link></li>
<li><Link className="a" to='/companies'>•Companies</Link></li>
<li><Link className="a" to='/services'>•Services</Link></li>
<li><Link className="a" to='/contact'>•Contact</Link></li>
</ul>
</div>
<hr/>
<Route path="/services" component={Services}/>
<Route path="/contact" component={Contact}/>
</div>
</Router>
</div>
);
}
}
const Home = () => (
<div>
<h2>Home</h2>
<div className="wrapper">
<div className="row">
<div className="ann"><div className="blink"><span>ANNOUNCEMENTS<br></br></span></div>*New launching of IT company Martl park Solutions in Technopark Thejswani Building 2nd Floor #12.00pm on 12th May 2018</div>
<div className="ann1"><div className="blink"><span>VACCANCIES </span></div>*No new Openings</div>
<div className="ann2"><h3 className="blink1"><span>Today's Highest Profit Closing Company </span></h3><b>*Tata Elxsi</b>(Nearer to 2crs.)</div>
<div className="ann3"><div className="blink"><span>EMERGING TECHNOLOGIES </span></div><div>*java</div><div>*JavaScript</div><div>*C##</div><div>*Python</div><div>*C++</div><div>*C</div></div>
</div>
</div>
</div>
);
const Services = () => (
<div>
<h2>Services</h2>
</div>
);
const Contact = () => (
<div>
<h2>Contact Us</h2>
<h3 className="inside">MULTIHAND ONLINE IT WORLD</h3>
<h4>Tech Arcade Building </h4>
<h4>Inside Technopark</h4>
<h4>Kazhakuttam P.O</h4>
<h4> Thiruvanathapuram </h4>
<hr/>
<h4 className="con"> ☏:- +91-9854631278</h4>
<h4 className="con"> ✉:- online#multihandworld.com</h4>
</div>
);
export default HomePage;
Can anyone suggests any idea to route correctly to the page.. Now only i got a blank page.. I want to load homepage first..
You're importing from named exports on your Routes, meanwhile you're using default exports on your actual components.
Instead of:
import { LoginForm } from './components/LoginForm/LoginForm';
Try doing this with the others as well:
import LoginForm from './components/LoginForm/LoginForm';
In my case, due to generating my project with create-react-app, a failure to notice this will give me an error like so:
148:112-120 './components/LoginForm/LoginForm' does not contain an export named 'LoginForm'.
Also, remove your Router from homepage.js and move the Routes into your routes.js into the Switch block:
render() {
return (
<div>
<Router>
<Switch>
<Route path="/" component={HomePage}/>
<Route path="/about" component={About}/>
<Route path="/loginform" component={LoginForm}/>
<Route path="/companies" component={Companies}/>
{/*Note services and contact is now in routes.js instead of homepage.js*/}
<Route path="/services" component={Services}/>
<Route path="/contact" component={Contact}/>
</Switch>
</Router>
</div>
);
}
Also make sure to import/move those components there as well.

Categories

Resources