This question already has an answer here:
Why I receive blank page? React
(1 answer)
Closed 11 months ago.
I've used BrowserRouter here, and wrapped the within a tag.
But the problem is, the ShowTodoList page is not rendering.
Is this syntactically correct?
App.js file
import {BrowserRouter, Route, Routes} from 'react-router-dom';
import React, { lazy } from 'react';
import "./App.scss";
const ShowTodoList = lazy(() => import("./components/showTodoList"));
const CreateTodo = lazy(() => import("./components/createTodo"));
function App() {
return (
<div className="app-contents">
TODO - LIST
<BrowserRouter>
<Routes>
<Route path="/" component={ShowTodoList} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
ShowTodoList.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { UpdateTodo } from "./updateTodo";
function TodoCard({ data, handleEdit, handleDelete }) {
const { _id, title, description } = data;
return (
<li key={_id}>
<div className="title-description">
<h3>{title}</h3>
<p>{description}</p>
</div>
<div className="button-container">
<button className="button" name={_id} onClick={handleEdit}>
edit
</button>
<button className="button" name={_id} onClick={handleDelete}>
delete
</button>
</div>
</li>
);
}
export function ShowTodoList() {
const [todo, setTodo] = useState([]);
const [open, setOpen] = useState(false);
const [id, setId] = useState("");
const [update, setUpdate] = useState(false);
useEffect(
function () {
axios
.get("http://localhost:8000/api/todo")
.then((res) => {
console.log(res.data);
setTodo(res.data);
})
.catch((err) => {
console.log(err.message);
});
},
[update]
);
function handleEdit(e) {
setId(e.target.name);
setOpen(true);
}
function handleUpdate() {
console.log("update:", update, !update);
setUpdate(!update);
}
function handleDelete(e) {
axios.delete(`http://localhost:8000/api/todo/${e.target.name}`);
setTodo((data) => {
return data.filter((todo) => todo._id !== e.target.name);
});
}
function handleClose() {
setId("");
setOpen(false);
}
return (
<section className="container">
<Link to="/create-todo" className="button-new">
<button className="button">New</button>
</Link>
<section className="contents">
<h1>TODO</h1>
<ul className="list-container">
{todo.map((data) => (
<TodoCard
data={data}
handleEdit={handleEdit}
handleDelete={handleDelete}
/>
))}
</ul>
</section>
{open ? (
<section className="update-container">
<div className="update-contents">
<p onClick={handleClose} className="close">
×
</p>
<UpdateTodo
_id={id}
handleClose={handleClose}
handleUpdate={handleUpdate}
/>
</div>
</section>
) : (
""
)}
</section>
);
}
I'm getting a blank page as below:enter image description here
Could anybody please check the codes and point out where I'm going wrong?
If you are using react-router version 6, we don't have component props in this version, and you should use element instead of it.
import { BrowserRouter, Route, Routes } from "react-router-dom";
import React, { lazy, Suspense } from "react";
const ShowTodoList = lazy(() => import("./components/showTodoList"));
const CreateTodo = lazy(() => import("./components/createTodo"));
function App() {
return (
<div className="app-contents">
TODO - LIST
<Suspense fallback={<div>Loading...</div>}>
<BrowserRouter>
<Routes>
<Route path="/" element={<ShowTodoList />} />
</Routes>
</BrowserRouter>
</Suspense>
</div>
);
}
export default App;
Related
I wanted to make a single blog page of a blog website to read but it's not working
I want someone help me to solve this error.
App.js
import Demo from "./components/Pages/Demo/Demo";
import DemoPost from "./components/Pages/Demo/Post";
function App() {
return (
<div>
<Routes>
<Route path='/posts' exact element={<Demo />} />
<Route path='/demo/:pid' element={<DemoPost />} />
</Routes>
</div>
);
}
export default App;
Posts.js
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
function Demo() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => setPosts(json))
}, []);
return (
<div className="posts">
<div className="grid">
{posts.map(post => (
<div key={post.id}>
<Link to={`/posts/${post.id}`}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</Link>
</div>
))}
</div>
</div>
)
}
export default Demo
Post.js
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
function Post({ match }) {
const [post, setPost] = useState([]);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts${match.params.pid}`)
.then(response => response.json())
.then(json => setPost(json))
console.log(match, 'why not show match');
}, []);
return (
<div className="posts">
<div className="post-container">
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
</div>
)
}
export default Post
For the link <Link to={`/posts/${post.id}`}> you need to render a route path that matches, e.g. path="/posts/:pid".
<Routes>
<Route path='/posts' exact element={<Demo />} />
<Route path='/posts/:pid' element={<DemoPost />} />
</Routes>
react-router-dom#6 Route components also no longer pass route props to the routed component. The element component should use the useParams hook to access the route path params.
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
function Post() {
const { pid } = useParams();
const [post, setPost] = useState();
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts/${pid}`)
.then(response => response.json())
.then(json => setPost(json));
}, [pid]); // <-- pid is effect dependency
if (!post) {
return null; // <-- or loading indicator/spinner/etc
}
return (
<div className="posts">
<div className="post-container">
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
</div>
);
}
I been stuck in this for a few days now, i cant find the way to pass the data dinamically from my SlideShow component to a Detail component, I used this as a way to display and filter the category within the same component.
import React, {useState} from 'react'
import styles from '../slideshow/SlideShow.module.css'
import BackToTopButton from '../BackToTopButton'
import { portafolio } from "../../data/dummydata"
import {
generatePath,
useNavigate
} from "react-router-dom";
const allCategory = [...new Set(portafolio.map((item) => item.category))]
const SlideShow = () => {
const [list, setList] = useState(portafolio)
const [category] = useState(allCategory)
const filterItems = (category) => {
const newItems = portafolio.filter((item) => item.category === category)
setList(newItems)
}
const [id, setId] = useState();
const navigate = useNavigate();
const handleProceed = (e) => {
id && navigate(generatePath("/project/:id", { id, filterItems }));
};
return (
<>
<div name='top' className={styles.subnav}>
<div className={styles.var}>
<ul className={styles.menu}>
{category.map((category) => (
<li>
<button onClick={() => filterItems(category)}>{category}</button>
</li>
))}
</ul>
</div>
</div>
<div className={styles.slideshow}>
<div className={styles.container}>
{list.map((items, i) => (
<div>
<a href={`/project/${id}`} key={i} onClick={(e) => {
setId(items.id);
}}>
<img onClick={handleProceed} src={items.cover} alt='' />
</a>
<div className={styles.text}>
<h5>{items.shortdes}</h5>
</div>
</div>
))}
</div>
<BackToTopButton />
</div>
</>
)
}
export default SlideShow
and here is the component where i want to display it, but it only passes the id parameter but not the rest of the data
import React from 'react'
import NavBar from '../navbar/NavBar'
import Footer from '../footer/Footer'
import styles from "../projectinfo/Description.module.css"
import { useParams } from 'react-router-dom'
const Projectinfo = () => {
const { id } = useParams();
console.log(id);
return (
<div >
<NavBar />
<div className={styles.Description}>
<div>
<div className={styles.main}>
<h2>{id}</h2>
<h4>{id.description}</h4>
</div>
<div className={styles.slideshow}>
<img src={id.cover} alt='' />
</div>
<h4>{id.shortdes}</h4>
</div>
</div>
<Footer />
</div>
)
}
export default Projectinfo
and here is the index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Info from './Info';
import Menu from './Menu';
import ProjectInfo from './components/projectinfo/Projectinfo';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<Routes>
<Route path='/' exact element={<Menu />} />
<Route path="/project/:id" element={<ProjectInfo />} />
<Route path='/info' element={<Info />} />
</Routes>
</BrowserRouter>
);
Before I used react-router-dom and I hadn't any problem and I changed my route without any problem.
But now I bring hook inside of my project and I got a problem.
When I use <NavLink>, my route changes but it does not render anything from my component. When I refresh my page, the component will appear.
My App.js:
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
const routes={
route: `/main/symbol/:title/:id`,
exact: true,
component: Symbol,
},
{
route: `/main/symbolDetails/:title/:id`,
exact: true,
component: SymbolDetails,
},
render(){
<Router>
<Switch>
{routes.map((route, k) => (
<Route
key={k}
exact={route.exact}
path={route.route}
component={route.component}
/>
))}
</Switch>
</Router>
}
My Home.js:
(in this component I use navlink for changing my page)
import GridContainer from "../../../components/Grid/GridContainer.js";
import "perfect-scrollbar/css/perfect-scrollbar.css";
// #material-ui/core components
import { makeStyles } from "#material-ui/core/styles";
// core components
import Navbar from "../../../components/Navbars/Navbar.js";
import Sidebar from "../../../components/Sidebar/Sidebar.js";
const useStyles = makeStyles(styles);
export default function Admin({ ...rest }) {
// styles
const classes = useStyles();
const [data, setData] = useState([]);
useEffect(() => getSymbolGroup(), []);
const getSymbolGroup = async () => {
let { data } = await symbolGroup.getSymbolGroup();
setData(data.data);
// console.log("data", data);
};
return (
<div className={classes.wrapper}>
<Sidebar
logoText={"Creative Tim"}
logo={logo}
color={color}
{...rest}
/>
<div className={classes.mainPanel}>
<Navbar
/>
<div className={classes.content}>
<div className={classes.container}>
<GridContainer>
{data &&
data.length &&
data.map((x, key) => {
return (
<div className="Subscrip Bshadow ">
<NavLink
to={`/main/symbol/${x.title}/${x.id}`}
className="a rightanime display awidth flexd"
exact
>
<div className="">
<div className="iconpro display">
<img
className="imgwidth "
src={`http://api.atahlil.com/Core/Download/${x.fileId}`}
/>
</div>
</div>
<div className="">
<p style={{ color: "#a3b0c3", width: "100%" }}>
{x.title}
</p>
</div>
</NavLink>
</div>
);
})}
</GridContainer>
</div>
</div>
)}
I realized my problem.
as I say it was correct when I use in class component.
it is not correct because of my useEffect (hook).
I had to use accolade (I mean {}) after use UseEffect in Home.js component.
home.js
useEffect(() => getSymbolGroup(), []); //it is not correct and I need to refresh my page to render
and the way I had to use useEffect is:
useEffect(() => {
getSymbolGroup();
}, []);
// its correct and does not need to refresh page
Futher to my last question here, I have been trying to map the refs to other routes. The scroll handler is working but ref.current is null. So I am looking for an answer to this dilema. Using no external dependencies, how can I fix this issue?
App.tsx
import React, { useEffect, useRef } from "react";
import { BrowserRouter, Route, NavLink, useLocation } from "react-router-dom";
import Home from "./pages/Home";
import "./styles.css";
const Header = ({ refs }) => {
const location = useLocation();
useEffect(() => {
console.log("location", location.pathname);
switch (location.pathname) {
case "/about":
scrollSmoothHandler(refs.aboutRef);
break;
case "/contact":
scrollSmoothHandler(refs.contactRef);
break;
case "/hero":
scrollSmoothHandler(refs.heroRef);
break;
default:
scrollSmoothHandler(refs.homeRef);
break;
}
}, [location, refs]);
const scrollSmoothHandler = ref => {
console.log("Triggered.");
console.log(ref.current);
//ref.current.scrollIntoView({ behavior: "smooth" });
};
return (
<>
<NavLink to="/hero" activeClassName="selected">
Hero
</NavLink>
<NavLink to="/about" activeClassName="selected">
About
</NavLink>
<NavLink to="/contact" activeClassName="selected">
Contact
</NavLink>
</>
);
};
function App() {
const homeRef = useRef(null);
const heroRef = useRef(null);
const aboutRef = useRef(null);
const contactRef = useRef(null);
return (
<div ref={homeRef} className="App">
<BrowserRouter>
<Header refs={{ aboutRef, contactRef, heroRef, homeRef }} />
<Route
exact
to="/"
refs={{ aboutRef, contactRef, heroRef, homeRef }}
component={Home}
/>
// More routes here.
</BrowserRouter>
</div>
);
}
export default App;
Home.tsx
import React, { Fragment, forwardRef, useRef } from "react";
import "../styles.css";
const Hero = forwardRef((props, ref) => {
return (
<section ref={ref}>
<h1>Hero Section</h1>
</section>
);
});
const About = forwardRef((props, ref) => {
return (
<section ref={ref}>
<h1>About Section</h1>
</section>
);
});
const Contact = forwardRef((props, ref) => {
return (
<section ref={ref}>
<h1>Contact Section</h1>
</section>
);
});
function Home(refs) {
const heroRef = useRef(refs.heroRef);
const aboutRef = useRef(refs.aboutRef);
const contactRef = useRef(refs.contactRef);
return (
<Fragment>
<Hero ref={heroRef} />
<About ref={aboutRef} />
<Contact ref={contactRef} />
</Fragment>
);
}
export default Home;
You can find a link to my Code Sandbox: here. Forks are much appreciated.
You cannot pass refs as props to other components with the name prop without using forwardRef on the commponent. You need to assign another name to it in order for it to work, For example innerRefs.
Also to pass on refs as prop to the Route component, make use of render prop method
App.tsx
import React, { useEffect, useRef } from "react";
import { BrowserRouter, Route, NavLink, useLocation } from "react-router-dom";
import Home from "./pages/Home";
import "./styles.css";
const Header = ({ innerRefs }) => {
const location = useLocation();
useEffect(() => {
console.log("location", location.pathname);
switch (location.pathname) {
case "/about":
scrollSmoothHandler(innerRefs.aboutRef);
break;
case "/contact":
scrollSmoothHandler(innerRefs.contactRef);
break;
case "/hero":
scrollSmoothHandler(innerRefs.heroRef);
break;
default:
scrollSmoothHandler(innerRefs.homeRef);
break;
}
}, [location, innerRefs]);
const scrollSmoothHandler = innerRef => {
console.log("Triggered.");
console.log(innerRef.current);
innerRef.current.scrollIntoView({ behavior: "smooth" });
};
return (
<>
<NavLink to="/hero" activeClassName="selected">
Hero
</NavLink>
<NavLink to="/about" activeClassName="selected">
About
</NavLink>
<NavLink to="/contact" activeClassName="selected">
Contact
</NavLink>
</>
);
};
function App() {
const homeRef = useRef(null);
const heroRef = useRef(null);
const aboutRef = useRef(null);
const contactRef = useRef(null);
return (
<div ref={homeRef} className="App">
<BrowserRouter>
<Header innerRefs={{ aboutRef, contactRef, heroRef, homeRef }} />
<Route
exact
to="/"
render={routeProps => (
<Home
{...routeProps}
innerRefs={{ aboutRef, contactRef, heroRef, homeRef }}
/>
)}
/>
// More routes here.
</BrowserRouter>
</div>
);
}
export default App;
Home.tsx
import React, { Fragment, forwardRef, useRef } from "react";
import "../styles.css";
const Hero = forwardRef((props, ref) => {
return (
<section ref={ref}>
<h1>Hero Section</h1>
</section>
);
});
const About = forwardRef((props, ref) => {
return (
<section ref={ref}>
<h1>About Section</h1>
</section>
);
});
const Contact = forwardRef((props, ref) => {
return (
<section ref={ref}>
<h1>Contact Section</h1>
</section>
);
});
function Home({ innerRefs }) {
return (
<Fragment>
<Hero ref={innerRefs.heroRef} />
<About ref={innerRefs.aboutRef} />
<Contact ref={innerRefs.contactRef} />
</Fragment>
);
}
export default Home;
Working demo here
I'm new in react and redux and im trying to create a private nested route .On Login i get redirected to /userdashboard also the token gets back from the server and gets stored to the local storage.
Whenever Im in http://localhost:3000/userdashboard/post the user gets loaded the posts get loaded.
But when i refresh the AUTH_ERROR action gets dispatched and the token gets removed from the local storage and i get redirected.
I've tried to call the same action for loading the user on the nested component but still the AUTH_ERROR action was dispatched
My App.js
import React, { Fragment, useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Landing from './components/layout/Landing/Landing';
import Register from './components/auth/Register';
import Login from './components/auth/Login';
import Alert from './components/layout/Alert/Alert';
import UserDasboard from './components/userdashboard/UserDashboard';
import PrivateRoute from './components/routing/PrivateRoute';
//Redux
import { Provider } from 'react-redux';
import store from './store';
import { loadUser } from './actions/auth';
import setAuthToken from './utils/setAuthToken';
import './App.scss';
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const App = () => {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<Router>
<Fragment>
<Alert />
<Switch>
<PrivateRoute path='/userdashboard' component={UserDasboard} />
<Route exact path='/register' component={Register} />
<Route exact path='/login' component={Login} />
<Route exact path='/' component={Landing} />
</Switch>
</Fragment>
</Router>
</Provider>
);
};
export default App;
//UserDashboard
import React, { Fragment, useEffect, useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import PropTypes from 'prop-types';
import Navbar from '../layout/Navbar/Navbar';
import SideBar from '../layout/SideBar/SideBar';
import Posts from '../../components/posts/Posts';
const UserDashboard = props => {
const [showSidebar, setShowSidebar] = useState(true);
const toggleSideBar = () => setShowSidebar(!showSidebar);
return (
<Router>
<Fragment>
<Navbar />
<div className='columns is-mobile'>
<SideBar showSidebar={showSidebar} />
<div className='column'>
<div className='columns is-mobile'>
<div
className='column is-2-desktop is-2-mobile'
onClick={toggleSideBar}
>
<button></button>
</div>
<div className='column is-3-desktop is-3-mobile is-offset-4'>
Dashboard
</div>
</div>
<Switch>
<Route path={props.match.url + '/post'} component={Posts} />
<Route
path={props.match.url + '/new-post'}
render={() => <p>Hello</p>}
/>
</Switch>
</div>
</div>
</Fragment>
</Router>
);
};
UserDashboard.propTypes = {};
export default UserDashboard;
//Post
import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import PostItem from './PostItem';
import { getPosts } from '../../actions/post';
const Posts = ({ getPosts, post: { posts, loading } }) => {
useEffect(() => {
getPosts();
}, [getPosts]);
return loading ? (
<p>Loading</p>
) : (
<Fragment>
<section className='section'>
<div className='columns'>
{/* Post form*/}
<div className='columns'>
{posts.map(post => (
<PostItem
key={post._id}
post={post}
subs={post.subscribedusers}
/>
))}
</div>
</div>
</section>
</Fragment>
);
};
Posts.propTypes = {
getPosts: PropTypes.func.isRequired,
post: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
post: state.post
});
export default connect(
mapStateToProps,
{ getPosts }
)(Posts);
//PostItem
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import Moment from 'react-moment';
import { connect } from 'react-redux';
import { addSubscriber, removeSubscriber } from '../../actions/post';
const PostItem = ({
addSubscriber,
removeSubscriber,
auth,
post: {
_id,
posttitle,
posttext,
postimage,
user,
subscribedusers,
userposts,
date
},
subs
}) => {
const sub = subs.map(sub => sub);
return (
<div className='column'>
<Link to={`/post/${_id}`}>
<div class='card'>
<div class='card-image'>
<figure class='image is-4by3'>
<img src={postimage} alt='Placeholder image' />
</figure>
</div>
<div class='card-content'>
<div class='media'>
<div class='media-left'>
<figure class='image is-48x48'>
<img
src='#'
alt='Placeholder image'
/>
</figure>
</div>
<div class='media-content'>
<p class='title is-4'>{posttitle}</p>
{/* <p class='subtitle is-6'>#johnsmith</p> */}
</div>
</div>
<div class='content'>
<p>{posttext}</p>
<br />
<time datetime='2016-1-1'>
<Moment format='YYYY/MM/DD'>{date}</Moment>
</time>
</div>
<footer class='card-footer'>
<p class='card-footer-item'>
Subscriptions{' '}
{subscribedusers.length > 0 && (
<span>{subscribedusers.length}</span>
)}
</p>
<p class='card-footer-item'>{userposts.length}</p>
<button className='button' onClick={e => addSubscriber(_id)}>
Subscribe
</button>
<button className='button' onClick={e => removeSubscriber(_id)}>
UnSubscribe
</button>
</footer>
</div>
</div>
</Link>
</div>
);
};
PostItem.propTypes = {
post: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(
mapStateToProps,
{ addSubscriber, removeSubscriber }
)(PostItem);
//loadUser in ./actions/auth
export const loadUser = () => async dispatch => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('userapi/auth');
dispatch({
type: USER_LOADED,
payload: res.data
});
} catch (err) {
dispatch({
type: AUTH_ERROR
});
}
};
//setAuthToken
import axios from 'axios';
const setAuthToken = token => {
if (token) {
axios.defaults.headers.common['x-auth-token'] = token;
} else {
delete axios.defaults.headers.common['x-auth-token'];
}
};
export default setAuthToken;