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>
);
Related
This question already has an answer here:
Difference in the navigation (React Router v6)
(1 answer)
Closed last month.
I am creating a website that is using React Router. All my links are working fine in the header but when I try to create a link on my home page it will not work. There must be a step I'm missing. Any help would be appreciated!
App:
import React, { useEffect } from "react";
import { useState } from 'react';
import { BrowserRouter, Routes, Route, Link } from "react-router-dom"
import Header from './Header';
import MilesForm from "./MilesForm";
import Weather from './Weather';
import PaceCalculator from "./PaceCalculator";
import WeeklyGoal from "./WeeklyGoal";
import Home from "./Home";
const getGoal = JSON.parse(localStorage.getItem('goal') || "[]");
const App = () => {
const [goal, setGoal] = useState(getGoal);
const [milesToGo, setMilesToGo] = useState();
const handleChange = (e) => {
setGoal(e.target.value)
}
const handleSubmit = (e) => {
e.preventDefault();
setMilesToGo(goal)
localStorage.setItem('goal', goal)
window.location.reload();
}
return (
<BrowserRouter>
<div>
<Header />
<Routes>
{/* <Route path="/" element={<Home />} /> */}
<Route path="Home" element={<Home />} />
<Route path="WeeklyGoal" element={[
<WeeklyGoal
handleChange={handleChange}
handleSubmit={handleSubmit}
goal={goal}
/>,
<MilesForm
goal={goal}
milesToGo={milesToGo}
setMilesToGo={setMilesToGo}
path="./MilesForm"
/>
]} />
<Route path="Weather" element={<Weather />} />
<Route path="Pace" element={<PaceCalculator />} />
</Routes>
</div>
</BrowserRouter>
);
};
export default App;
Header:
import React from "react";
import './css/header.css';
import { Link } from 'react-router-dom';
import { useState } from 'react';
const Header = () => {
const [burger, setBurger] = useState(true)
const handleToggle = () => {
{ burger ? setBurger(false) : setBurger(true) }
}
return (
<div className="header-style">
<h1 className="header-title">3-2run</h1>
<button className="burger-btn" onClick={handleToggle}>
<p></p>
<p></p>
<p></p>
</button>
<div
className={burger === false
? "menu-container"
: "hide-menu-container"
}
>
<ul>
<li><Link to="Home">Home</Link></li>
<li><Link to="WeeklyGoal">Track your miles</Link></li>
<li><Link to="Weather">Weather</Link></li>
<li><Link to="Pace">Pace Calculator</Link></li>
</ul>
</div>
</div>
)
}
export default Header;
Home: Here I have a link to the weather page that is not working. I'm confused as to why this same link will work on the header page but not on this one.
import React from 'react';
import './css/home.css';
import { Link } from 'react-router-dom'
const Home = () => {
return (
<div className='home-container'>
<div className='track-miles-link'>
<h2>Track Your Miles</h2>
</div>
<div className='get-weather'>
<Link to="Weather"><h2>Check Weather</h2></Link>
</div>
<div className='get-pace'>
<h2>Pace Calculator</h2>
</div>
</div>
)
}
export default Home;
You don't have a route with the path /Home/Weather so
<Link to="Weather"><h2>Check Weather</h2></Link>
won't work
You have /Weather route so
<Link to="/Weather"><h2>Check Weather</h2></Link>
or
<Link to="../Weather"><h2>Check Weather</h2></Link>
will work
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;
I am having a react-quiz application whose code is:
Quiz.js file:
const Quiz = (props) => {
const [options,setOptions]=useState();
const [questions,setQuestions]=useState(props.questions);
const [currentQuestion,setCurrentQuestion]=useState(0);
useEffect(()=>{
console.log(questions);
var optionss=[];
optionss.push(questions[currentQuestion].correct_answer);
questions[currentQuestion].incorrect_answers.forEach((ans)=>optionss.push(ans));
optionss.sort(()=>Math.random()-0.5);
setOptions(optionss);
},[options])
return (
<div className='quiz'>
<span className="subtitle">Welcome ,{props.name}</span>
<div className="questionInfo">
<span>{questions[currentQuestion].category}</span>
<span>Score : {props.score}</span>
</div>
<Question
questions={questions}
setQuestions={setQuestions}
currentQuestion={currentQuestion}
setCurrentQuestion={setCurrentQuestion}
options={options}
correctOption={questions[currentQuestion].correct_answer}
score={props.score}
setScore={props.setScore}
/>
</div>
);
};
export default Quiz;
Question.js file:
const Question = ({
questions,
setQuestions,
currentQuestion,
setCurrentQuestion,
options,
correctOption,
score,
setScore
}) => {
useEffect(()=>{
},[]);
console.log(options);
<h1>Question : {currentQuestion+1}</h1>
<div className="singleQuestion">
<h2>{questions[currentQuestion].question}</h2>
<div className="options">
{options.map((option)=>{
return(
<button
disabled={selected}
key={option}
onClick={()=>{}}
className={`singleOption ${selected && handleSelect(option)}`}
>{option}</button>
)
})}
</div>
</div>
App.js file:
import { BrowserRouter,Routes,Route} from 'react-router-dom';
import './App.css';
import Quiz from './components/quiz/quiz';
import axios from "axios"
import {useState} from 'react'
import Home from './components/home/home';
import Header from './components/header.js';
import Result from './components/result/result';
import Footer from './components/footer';
import { useEffect } from 'react';
function App() {
const [name,setName]=useState("");
const [score,setScore]=useState(0);
const [questions,setQuestions]=useState();
useEffect(()=>{
console.log("Questions have changed");
},[questions]);
const fetchQuestions=async(category,difficulty)=>{
const {data}=await axios(`https://opentdb.com/api.php?amount=10&category=${category}&difficulty=${difficulty}&type=multiple`);
setQuestions(data.results);
}
return (
<BrowserRouter>
<div className="App" style={{backgroundImage: "url(./ques1.png)"}}>
<Header/>
<Routes>
<Route path="/home" exact element={<Home name={name} setName={setName} fetchQuestions={fetchQuestions}/>}></Route>
<Route path="/quiz" exact element={<Quiz name={name} questions={questions} score={score} setScore={setScore} />}></Route>
</Routes>
<Footer></Footer>
</div>
</BrowserRouter>
);
}
export default App;
Even though my Quiz component is able to get the questions from the App component,however when I send the question,options to the Question component as props from the Quiz component,I get undefined on logging in the Question component.
UseEffect in Quiz.js file has no dependencies: [], it will only run once, for first component rendering. Pass there the value that you want to watch for: [options]
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;