React: How to direct new page - reactjs

I am beginner in React js. I am developing projects about getting pokemons with API from pokeApi. I was able to get all pokemons(name,id, and image) from there. However I want to get more detail. When I click one pokemon I want to see more detail about it.
This is my PokemonCard.js
<Router>
<StyledLink to={`pokemon/${this.state.pokemonIndex}`}>
<Card className="card">
<h5 className="card-header">{this.state.pokemonIndex}</h5>
.
.
.
</Card>
</StyledLink>
</Router>
When I click one pokemon the url changes from localhost:3000 to http://localhost:3000/pokemon/7. However, nothing shows up.
this is my Pokemon.js
import axios from 'axios';
import React, { Component } from 'react'
export default class Pokemon extends Component {
state = {
name: '',
pokemonIndex: '',
imageUrl: ''
};
async componentDidMount() {
const { pokemonIndex } = this.props.match.params;
// Urls for pokemon information
const pokemonUrl = `https://pokeapi.co/api/v2/pokemon/${pokemonIndex}/`;
const pokemonSpeciesUrl = `https://pokeapi.co/api/v2/pokemon-species/${pokemonIndex}/`;
//get information about pocekoms
const pokemonRes = await axios.get(pokemonUrl);
const name = pokemonRes.data.name;
this.setState({name})
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
</div>
)
}
}
What did I wrong? Please explain to me. I am beginner in this language. Thanks for your time and help.

Issues
You are wrapping each PokemonCard with it's own Router, you need only 1 single Router wrapping the entire app.
You've not any Route components rendering the UI.
Solution
index.js - Import a Router and wrap the app.
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById("root")
);
App.js - Render the UI components into Route components within a Switch so only a single route is rendered at-a-time.
...
import { Switch, Route } from "react-router-dom";
import Pokemon from "./components/pokemon/Pokemon";
...
function App() {
return (
<div className="App">
<NavBar />
<div className="container">
<Switch>
<Route path="/pokemon/:pokemonIndex" component={Pokemon} />
<Route path="/">
<Dashboard />
</Route>
</Switch>
</div>
</div>
);
}
PokemonCard.js - Remove the extraneous Router components.
...
render() {
return (
<div className="col-md-3 col-sm-6 mb-5">
<StyledLink to={`pokemon/${this.state.pokemonIndex}`}>
<Card className="card">
...
</Card>
</StyledLink>
</div>
);
}

I think you are missing Route with the routes you want your component to be rendered
<Switch>
<Route exact path="pokemon/:id">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Related

My react onClick navigate shows URL, but does not render component

I am new to React router here and I am trying to make clicking on a recipe in my 'BrowseRecipes' page redirect to a page dedicated to that recipe. However, when I click on the recipe, the URL shows the correct URL /browse/${recipeID}, but the page I assign to this route does not render. Only the /browse page with a list of all the recipes renders. Does anyone know why?
Here is my APP.js
import AddNewRecipe from './components/AddNewRecipe'
import BrowseRecipes from './components/BrowseRecipes'
import { currentState } from './components/redux';
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Switch, Route, Routes, Link, useParams} from "react-router-dom";
import AuthReqPage from "./components/AuthReqPage"
import Navbar from "./components/Navbar"
import RecipePage from "./components/BrowseRecipes/RecipePage"
import PageNotFound from "./components/PageNotFound"
function App(props) {
return (
<Router>
<div className="App">
<Navbar />
<Routes>
<Route path='/add' element={<AddNewRecipe />} />
<Route path='/' element={<BrowseRecipes />} />
<Route path='/browse' element={<BrowseRecipes />}>
<Route path=':recipeID' element={<RecipePage />}/>
</Route>
<Route path='/authrequired' element={<AuthReqPage />} />
<Route path='/*' element={<PageNotFound />} />
</Routes>
</div>
</Router>
);
}
export default App;
Here is my BrowseRecipe component/page:
export function BrowseRecipes (props){
console.log('browseRecipe running')
let navigate = useNavigate()
let params=useParams()
console.log(params.recipeID)
if(props.recipeStore.length>0)
{
var displayRecipes = props.recipeStore.map(
elem=>
{
return (<li key={elem.recipeID} className='recipeDisplayBox' onClick={()=>navigate(`/browse/${elem.recipeID}`)}>
{elem.title},
Prep: {elem.prepTime.numeral} {elem.prepTime.unit}
</li>)
}
)
}
return(
<div>
<h1>Browse Recipes</h1>
<h2>Your recipes:</h2>
<ul>
{displayRecipes}
</ul>
</div>
)
}
const mapStateToProps=(state)=>{
return {recipeStore: state.recipe}}
export default connect(mapStateToProps)(RequireAuth(BrowseRecipes))
And here is the individual recipe page that failed to render:
export function RecipePage (props){
console.log('RecipePage running')
let params=useParams()
return(
<div>
<h1>{params.recipeID}</h1>
</div>
)
}
const mapStateToProps=(state)=>{
return {recipeStore: state.recipe}}
export default connect(mapStateToProps)(RequireAuth(RecipePage))
"RequireAuth" here is a higher-order component that redirects the page to 'Please Sign In' page if the user is not signed in.
Did I misunderstand something about the use of UseParams? Please help me shed some light! Thank you very much
You've rendered the RecipePage component on a nested route from the "/browse" route rendering the BrowseRecipes component.
<Route path='/browse' element={<BrowseRecipes />}>
<Route path=':recipeID' element={<RecipePage />}/>
</Route>
In this configuration the BrowseRecipes is required to render an Outlet component for the nested routes to be rendered into.
Example:
import { Outlet, useNavigate, useParams } from 'react-router-dom';
export function BrowseRecipes (props) {
const navigate = useNavigate();
const params = useParams();
let displayRecipes;
if (props.recipeStore.length) {
displayRecipes = props.recipeStore.map(elem => {
return (
<li
key={elem.recipeID}
className='recipeDisplayBox'
onClick={() => navigate(`/browse/${elem.recipeID}`)}
>
{elem.title},
Prep: {elem.prepTime.numeral} {elem.prepTime.unit}
</li>
);
});
}
return (
<div>
<h1>Browse Recipes</h1>
<h2>Your recipes:</h2>
<ul>
{displayRecipes}
</ul>
<Outlet /> // <-- nested routes render here
</div>
);
}
If you don't want to render both BrowseRecipes and RecipePage at the same time, then create a nested index route specifically for BrowseRecipes.
Example:
<Route path='/browse'>
<Route index element={<BrowseRecipes />} /> // <-- "/browse"
<Route path=':recipeID' element={<RecipePage />} /> // <-- "/browse/:recipeID"
</Route>
For more information, see:
Index Routes
Layout Routes

useParams() for none route components in ReactJS

Please go through my App.js
<Provider store={reduxStore}>
<Router basename={process.env.PUBLIC_URL}>
<Container>
<Navigation /> <----------------------------------- HERE
<div className="wrapper">
<Switch>
<PublicRoute exact path={PATHS.HOME} component={Home} />
</Switch>
</div>
<Footer/> <---------------------------------------- HERE
</Container>
</Router>
</Provider>
Navigation is use in all components so I added that component in App.js. For sure, this component has no route linked to it. BUT:
In Navigation and Footer, I want to use useParams().
Navigation.js
import React from 'react';
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import { withRouter, useParams } from 'react-router-dom';
const Navigation = (props) => {
const { slug } = props;
return (
<>
<Navbar>
<Nav>
<Nav.Link>
Home
</Nav.Link>
</Nav>
</Navbar>
</>
);
};
export default withRouter(Navigation);
My current url:
localhost:3000/event/:slug
I do recieve props, but I could not find slug
try remove exact ?
<Switch>
<PublicRoute path={PATHS.HOME} component={Home} />
</Switch>

React router structure for dashboard component

Hi i am new developer in ReactJS. I have a problem and want to learn how to make routing for dashboard. My root component is App component and it calls only dashboards of my pages. But I want to call different components inside of dashboard such as Login , Register etc. When I use "Link" in anywhere, How can I do this ? Could you help me at this issue?
index.tsx for BrowserRouter
import {BrowserRouter} from "react-router-dom";
const app =<App /> ;
const container = (
<>
<BrowserRouter>
{app}
</BrowserRouter>
</>
);
my router App.tsx component:
import { Route, Switch } from "react-router-dom";
import LoginDash from "../containers/login/LoginDash"
class App extends Component {
render() {
return (
<div className="App">
<Switch>
<Route path="/Login" exact component={LoginDash}></Route>
<Route path="/" exact component={LoginDash}></Route>
</Switch>
</div>
);
}
}
export default App;
My dashboard LoginDash.tsx:
import {BrowserRouter as Router, Route,Switch} from "react-router-dom"
import LoginPart from "../../components/login/left/LoginPart";
import RegisterPart from "../../components/login/left/RegisterPart";
import AnitamionPart from '../../components/login/right/AnimationPart';
export const Login = () => {
return (
<div className="login-container">
<div className="row login-row" >
<div className="login-left-part" >
<Router>
<Switch>
<Route exact path = "/Login" component={LoginPart}></Route>
<Route exact path = "/Register" component={RegisterPart}></Route>
</Switch>
</Router>
</div>
<div className=" login-right-part" >
<AnitamionPart></AnitamionPart>
</div>
</div>
</div>
)
}
export default Login;
First of all, you only need to use one instance of BrowserRouter in your App, Since you already wrap App component with BrowserRouter that would be enough
Secondly, if you specify exact attribute on Routes, no nested Routes will ever match. Make sure you don't use Route with exact prop if the component has any nested Route defined
Lastly, you only need to render LoginDash on / route, /Login handling can be done separately as a nested Route
Update your individual components like below
import {BrowserRouter} from "react-router-dom";
// Do not render app as a constant separetely,
const container = (
<>
<BrowserRouter>
<App />
</BrowserRouter>
</>
);
import { Route, Switch } from "react-router-dom";
import LoginDash from "../containers/login/LoginDash"
class App extends Component {
render() {
return (
<div className="App">
<Route path="/" component={LoginDash}></Route>
</div>
);
}
}
export default App;
export const Login = () => {
return (
<div className="login-container">
<div className="row login-row" >
<div className="login-left-part" >
<Switch>
<Route exact path = "/Login" component={LoginPart}></Route>
<Route exact path = "/Register" component={RegisterPart}></Route>
</Switch>
</div>
<div className=" login-right-part" >
<AnitamionPart></AnitamionPart>
</div>
</div>
</div>
)
}
export default Login;
Working demo

Cannot render child components with React Router (Nested Routes)

I am trying to use nested routes to render different components. When I click my links, URL does update but the components are not rendering. Prior to this I was using imported components, but since that wasn't working, I stripped it down to this block of code and it's still just showing a blank component and no errors.
import React from 'react';
import { Route, Switch, Link, useRouteMatch } from 'react-router-dom';
function InfluencerComponent() {
let { path, url } = useRouteMatch();
const navLinks = (
<div>
<Link to={`${url}/select-trade`}>Select trade</Link>
<Link to={`${url}/add-skills`} className="ml-2">
Add skills
</Link>
</div>
);
return (
<div className="row mt-3">
<Switch>
<Route exact path={path}>
{navLinks}
</Route>
<Route path={`${path}/select-trade`}>
{navLinks}
<Test />
</Route>
<Route path={`${path}/add-skills`}>
{navLinks}
<TestTwo />
</Route>
</Switch>
</div>
);
}
function Test() {
return 'Test Component';
}
function TestTwo() {
return 'Another Test Component';
}
export default InfluencerComponent;
Components are not rendering because you should use component prop instead of children.
Example:
return (
<div className="row mt-3">
<Switch>
// ...
<Route path={`${path}/add-skills`} component={<>{navLinks}<TestTwo /></>} />
</Switch>
</div>
);
More info about <Route /> props:
https://reacttraining.com/react-router/web/api/Route/component

React-Router nested routes loading blank page instead of loading inside parent component

I am new to React and trying to create a layout with nested routes. Here's my scenario
show Login when URL is /
show Dashboard when URL is /dashboard
show Profile when URL is /dashboard/profile (this should load
inside the dashboard content area)
The login page and dashboard page are loading properly when the URL is accessed in the browser but for /dashboard/profile, the browser goes to a blank page instead of loading it inside the dashboard component.
Index.js
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'));
App.js
class App extends Component {
render() {
return (
<div>
{/* <Switch> */}
<Route exact path='/' component={SignIn}/>
<Route exact path='/dashboard' component={Dashboard}/>
{/* </Switch> */}
</div>
);
}
}
export default App;
Dashboard.js
class Dashboard extends React.Component {
render() {
const { classes } = this.props;
return (
<React.Fragment>
<CssBaseline />
<div className={classes.root}>
<Header classes={classes} open={this.state.open} click={this.handleDrawerOpen} />
<Sidebar classes={classes} open={this.state.open} click={this.handleDrawerClose} />
<main className={classes.content}>
<div className={classes.appBarSpacer} />
*********I expect profile component to load here
but when I access the URL /dashboard/profile I get a new blank page*********
Route path="/dashboard/profile" exact component={Profile} />
</main>
</div>
</React.Fragment>
);
}
}
You need to remove the exact prop from the Dashboard route (present in Switch) while doing the child routing.
This is the minimal implementation of your use case:
import React, { Component } from "react";
import "./styles.css";
import {
NavLink,
Redirect,
Route,
BrowserRouter as Router,
Switch
} from "react-router-dom";
const App = () => (
<Router>
<div className="App">
<ul>
<li>
<NavLink to="/login">Login</NavLink>
</li>
<li>
<NavLink to="/dashboard">Dashboard</NavLink>
</li>
</ul>
<Switch>
<Route exact path="/login" component={Login} />
<Route path="/dashboard" component={Dashboard} />
</Switch>
</div>
</Router>
);
const Login = () => <span>Login Page</span>;
const Dashboard = () => {
return (
<div>
<div>Dashboard Page</div>
<NavLink to="/dashboard/profile">Go to profile</NavLink>
<div>
<Route exact path="/dashboard/profile" component={Profile} />
</div>
</div>
);
};
const Profile = () => {
return <span>Profile Page</span>;
};
export default App;
You can find the working example here:https://codesandbox.io/s/z3py3672v3

Resources