App.jsx
import { useState } from 'react';
import './App.css';
import NewsContainer from './Components/NewsContainer';
import { Router, Routes, Route } from "react-router-dom"
function App() {
const [mode, setMode] = useState("light")
const changeMode = () => {
if (mode === "light") {
setMode("dark")
document.body.style.backgroundColor = "rgb(30 41 59)"
} else {
setMode("light")
document.body.style.backgroundColor = "white"
}
}
return (
<Router>
<div className='justify-evenly'>
<Routes>
<Route exact path="/" element={<NewsContainer key="general" mode={mode} changeMode={changeMode} category="general" />} />
<Route exact path='/sports' element={<NewsContainer key="sports" mode={mode} changeMode={changeMode} category="sports" />} />
<Route exact path='/buisness' element={<NewsContainer key="buisness" mode={mode} changeMode={changeMode} category="buisness" />} />
<Route exact path='/entertainment' element={<NewsContainer key="entertainment" mode={mode} changeMode={changeMode} category="entertainment" />} />
<Route exact path='/health' element={<NewsContainer key="health" mode={mode} changeMode={changeMode} category="health" />} />
</Routes>
</div>
</Router>
);
}
export default App;
Navbar.jsx
import { Link } from "react-router-dom";
function Navbar({ mode, changeMode }) {
return (
<div
className={`${mode === "light" ? "bg-gray-100" : "dark : bg-slate-900"} `}
>
<header className="text-gray-600 body-font">
<div className="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center">
<li
className={`flex title-font font-medium list-none items-center text-${
mode === "light " ? "gray-900" : "white"
} mb-4 md:mb-0 cursor-pointer`}
>
<span
className={`ml-3 text-xl text-${
mode === "light" ? "black" : "white"
}`}
>
<Link to="/">Hind News</Link>
</span>
</li>
<nav className="md:mr-auto md:ml-4 md:py-1 md:pl-4 md:border-l md:border-gray-400 flex flex-wrap items-center text-base justify-center list-none cursor-pointer">
<li
className={`mr-5 hover:text-${
mode === "light" ? "dark : gray-900" : "white"
}`}
>
<Link to="/sport"> Sports </Link>
</li>
<li
className={`mr-5 hover:text-${
mode === "light" ? "dark : gray-900" : "white"
}`}
>
<Link to="/buisness">Buisness </Link>
</li>
<li
className={`mr-5 hover:text-${
mode === "light" ? " dark:gray-900" : "white"
}`}
>
<Link to="/entertainment">Entertainment </Link>
</li>
<li
className={`mr-5 hover:text-${
mode === "light" ? "dark : gray-900" : "white"
}`}
>
<Link to="/health">Health </Link>
</li>
</nav>
<input
type="text"
className="inline-flex items-center bg-gray-200 border-0 py-1 px-3 focus:outline-none hover:bg-gray-300 rounded text-base mt-4 md:mt-0"
/>
<button className="inline-flex items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0">
Search
<svg
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
className="w-4 h-4 ml-1"
viewBox="0 0 24 24"
>
<path d="M5 12h14M12 5l7 7-7 7"></path>
</svg>
</button>
<div className="flex justify-center">
<div className="flex justify-center">
<div className="form-check form-switch">
<input
className="form-check-input appearance-none w-9 -ml-10 rounded-full float-left h-5 align-top bg-white bg-no-repeat bg-contain bg-gray-300 focus:outline-none cursor-pointer shadow-sm ml-60"
type="checkbox"
role="switch"
id="flexSwitchCheckDefault"
onClick={changeMode}
/>
<label
className={`form-check-label inline-block text-${
mode === "light" ? "gray-900" : "white"
} `}
htmlFor="flexSwitchCheckDefault"
>
{" "}
Switch Mode
</label>
</div>
</div>
</div>
</div>
</header>
</div>
);
}
export default Navbar;
Error on console
Uncaught TypeError: Cannot read properties of undefined (reading
'pathname')
The above error occurred in the <Router> component:
at Router (http://localhost:3000/static/js/bundle.js:39615:15)
at App (http://localhost:3000/static/js/bundle.js:33:74)
Consider adding an error boundary to your tree to customize error
handling behavior. Visit https://reactjs.org/link/error-boundaries to
learn more about error boundaries.
You probably want to use the BrowserRouter instead of Router, which is a wrapper around Router.
you got a typo in there.
<Link to="/sport"> Sports </Link>
when in the Route it spells sports
<Route exact path='/sports' element={<NewsContainer key="sports" mode={mode} changeMode={changeMode} category="sports" />} />
Hope it solves it
Issue
You are importing and rendering the low-level Router component and not passing any of the required props.
import { Router, Routes, Route } from "react-router-dom"
Router
declare function Router(
props: RouterProps
): React.ReactElement | null;
interface RouterProps {
basename?: string;
children?: React.ReactNode;
location: Partial<Location> | string; // <-- missing
navigationType?: NavigationType;
navigator: Navigator; // <-- missing
static?: boolean;
}
Missing are the location and navigator props. The error is specifically due to the missing location prop, it's undefined, so the code can't access pathname of `undefined.
Solution
You almost never need to render Router yourself manually. You should instead render one of the high-level routers (e.g. BrowserRouter, HashRouter, etc) that instantiates and maintains a history reference and passes these required props to the low-level Router component.
Example:
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
Related
I have created a navbar component in my react app using tailwindcss for styling. I have imported react-router-dom#6.6.1 and tried to set up routes but can't get my pages/routes to show up.
Index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
App.js
import React from "react";
import "./App.css";
import { Route, Routes } from "react-router-dom";
import Home from "./routes/Home.js";
import About from "./routes/About.js";
import Navbar from "./components/Navbar";
import Footer from "./components/Footer";
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" exact element={<Home />}></Route>
<Route path="/About" element={<About />}></Route>
</Routes>
<Footer />
</>
);
}
export default App;
Home page
import React from "react";
const Home = () => {
return (
<div>
<h1 className="text-black text-3xl">Home</h1>
</div>
);
};
export default Home;
I would expect to see Home appear on the "/" route when I click on the home link on the navbar and the same for About. However, I don't seem to be returning any routes.
About page:
const About = () => {
return <h1>About Wick House</h1>;
};
export default About;
Navbar
import React, { useState } from "react";
import { Link } from "react-router-dom";
const Navbar = () => {
let [open, setOpen] = useState(false);
return (
<header className="w-full fixed top-0 left-0 bg-slate-400 h-14">
<nav className="md:flex items-center justify-between px-[8%] ">
<div
className=" text-base cursor-pointer flex items-center
text-white gap-4 pt-2"
>
<img
src="/wickhouse-logo-192x192.png"
className="w-10 rounded"
alt="Wick House Publishing Logo"
/>
<h1>WICK HOUSE PUBLISHING</h1>
</div>
<div
onClick={() => setOpen(!open)}
className="text-3xl text-white absolute right-[8%] top-3 cursor-pointer md:hidden"
>
<ion-icon name={open ? "close" : "menu"}></ion-icon>
</div>
<ul
className={`md:flex md:items-center md:pt-2 absolute md:static md:bg-slate-400 bg-slate-600 md:z-auto z-[10] left-0 w-full md:w-auto md:pl-0 pl-[8%] md:transition-none transition-all duration-500 ease-in ${
open ? "top-14 " : "top-[-490px]"
}`}
>
<li className=" md:ml-8 text-base md:my-0 my-4">
<Link
to="/"
className="text-white hover:text-gray-300 duration-500"
>
HOME
</Link>
</li>
<li className=" md:ml-8 text-base md:my-0 my-4">
<Link
to="/About"
className="text-white hover:text-gray-300 duration-500 md:ml-8 text-base md:my-0"
>
ABOUT
</Link>
</li>
<li className=" md:ml-8 text-base md:my-0 my-4">
<Link
to="/Authors"
className="text-white hover:text-gray-300 duration-500 md:ml-8 text-base md:my-0"
>
AUTHORS
</Link>
</li>
<li className=" md:ml-8 text-base md:my-0 my-4">
<Link
to="/Contact"
className="text-white hover:text-gray-300 duration-500 md:ml-8 text-base md:my-0"
>
CONTACT
</Link>
</li>
</ul>
</nav>
</header>
);
};
export default Navbar;
I have tried the documentation, guides, youtube and can't figure it out.
My code is not working. Here is my App.js file:
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Dashboard />} >
<Route path="teachers" element={<Teachers />} >
<Route exact path="single/:id" element={<SingleTeacher />} />
</Route>
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}
Here is my code where I am routing the teachers/single/{id} route:
export default function TeacherCard({ name, spacial_at, teacher_pic_url, _id }) {
return (
<div className="bg-white shadow-lg py-4 px-3 rounded-lg flex md:flex-row flex-col justify-between items-center">
<div className='relative'>
<img className='h-16 w-16 object-cover rounded-full' src={teacher_pic_url} alt={name} loading={'lazy'} />
<span className='absolute bottom-1 right-1 rounded-full px-1 py-1 bg-green-500 border border-white'></span>
</div>
<div className='flex md:pl-3 flex-col w-2/3 text-center md:text-left'>
<span className=' font-semibold text-md'>{name}</span>
<span className='text-gray-400 text-xs'>{spacial_at}</span>
<Link to={`single/${_id}`} className='text-grad-to text-xs mt-2 md:text-left'>View profile</Link>
</div>
</div>
)
}
This code takes me to the route successfully but I can't get the id params in <SingleTeacher /> route. Here is my SingleTeacher.js file:
export default function SingleTeacher() {
console.log(useParams());
return (
<div>SingleTeacher</div>
)
}
But It can't be logging any information to the console.
Given:
<Route path="teachers" element={<Teachers />} >
<Route exact path="single/:id" element={<SingleTeacher />} />
</Route>
Then it seems this Teachers component as a layout route is missing rendering an Outlet component for the nested route rendering SingleTeacher.
Example:
import { Outlet } from 'react-router-dom';
const Teachers = () => {
....
return (
<>
....
<Outlet /> // <-- nested routes render element here
....
</>
);
};
See:
Layout Routes
Outlet
I am having trouble with React while trying to set a token for user to log into the application. I followed the steps here to create a login process but it gives out the Unhandled Rejection (TypeError): setToken is not a function error and I am not able to correct it.
Here are the associated codes starting with from app.js
import React from 'react';
import { useState } from 'react';
import Login from './Pages/Login.js';
import Signup from './Pages/Signup';
import Dashboard from './Pages/Dashboard.js';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import useToken from './Pages/useToken'
function App() {
const { token, setToken } = useToken();
if (!token) {
return <Login setToken={setToken} />
};
return (
<div className="">
<BrowserRouter>
<Switch>
<Route exact path="/">
<Login />
</Route>
<Route exact path="/dashboard">
<Dashboard />
</Route>
<Route exact path="/signup">
<Signup />
</Route>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
Login.js
import React from 'react';
import { useState } from 'react';
import PropTypes from 'prop-types';
async function loginUser(credentials) {
return fetch('http://localhost:8080/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(credentials)
})
.then(data => data.json())
}
const Login = ({setToken}) => {
// username is email address
const [username, setUsername] = useState();
const [password, setPassword] = useState();
const handleSubmit = async(e) => {
e.preventDefault();
const token = await loginUser({
username,
password
});
setToken(token);
};
return (<>
<section>
<div className="flex items-center justify-center flex-col">
<div className="w-11/15 mt-24 rounded-lg flex flex-col items-center justify-center relative">
<span className="flex flex-col lg:flex-row">
<header className="text-5xl pr-4">Welcome to </header>
<header className="font-LoveloLine text-6xl font-bold text-center"> Mused</header>
</span>
</div>
</div>
</section>
<section>
<div className="flex items-center justify-center flex-col">
<div className=" lg:w-2/4 px-4 rounded-lg flex flex-col items-center justify-center relative" >
<div className="py-12">
<form action="" className="flex flex-col gap-2" onSubmit={handleSubmit}>
{/* Email address */}
<label htmlFor=""></label>
<input className="w-96 text-brand-Black bg-white border-brand-Blue rounded-lg py-3 focus:outline-none focus:ring-2 focus:ring-brand-Red focus:border-transparent" type="email" name="" placeholder="Email address" id="" onChange={(e) => { setUsername(e.target.value)}} />
<label htmlFor=""></label>
{/* Password */}
<input className="w-96 bg-white text-brand-Black border-brand-Blue rounded-lg py-3 focus:outline-none focus:ring-2 focus:ring-brand-Red focus:border-transparent" type="password" name="" placeholder="Password" id="" onChange={(e) => { setPassword(e.target.value)}} />
<div class="max-w-sm mx-auto py-4">
<label class="inline-flex items-center">
<input class="text-brand-Blue w-6 h-6 mr-2 focus:ring-indigo-400 focus:ring-opacity-25 border border-gray-300 rounded" type="checkbox" />
Remember me
</label>
</div>
{/* Login button */}
<div>
<button type="submit" className="bg-brand-Blue rounded-full w-full py-2 active:bg-brand-Blue-dark hover:bg-brand-Blue-dark">Login</button>
</div>
</form>
{/* Checkbox */}
{/* Signup button */}
<div className="flex flex-col items-center justify-center ">
<p className="py-6">or</p>
<button type="submit" className="bg-brand-Red rounded-full w-full py-2 active:bg-brand-Red-dark hover:bg-brand-Red-dark">Signup
</button>
</div>
</div>
</div>
</div>
</section>
</>
)
};
Login.propTypes = {
setToken: PropTypes.func.isRequired,
}
export default Login
Error is thrown for Login.js file "setToken(token)" function. It is not supposed to be a function
import { useState } from 'react';
const useToken = () => {
const getToken = () => {
const tokenString = localStorage.getItem("token");
const userToken = JSON.parse(tokenString);
return userToken?.token
};
const [token, setToken] = useState(getToken());
const saveToken = (userToken) => {
localStorage.setItem("token", JSON.stringify(userToken));
setToken(userToken.token);
}
return {
setToken: saveToken,
token
}
}
export default useToken
In my own case i discovered that I was passing the setToken function inside login route like this:
<Route path='/login setToken={setToken} />
instead of
<Route path='/login' exact element={<Login
setToken={setToken}
/>}
/>
You have to pass it to the component itself, not the route!
Your posting this as within only the component, as soon as you go to the route it disregards it. So from localhost:3000 it'll work fine, but because you've not passed it through the route setToken={token} it'll disregard it. Scratched my head at this for hours.
In my react app I have a file called SecondaryLayout.js
const SecondaryLayout = ({children, className, ...rest}) => {
return (
<>
<Sidebar />
<main className={['seconday_layout__container', className].join('')} {...rest}>
{children}
</main>
</>
);
};
Sidebar.js:
const Sidebar = () => {
const {user} = useSelector(state => state.auth);
return (
<div className="bg-white py-4 px-2 fixed h-screen shadow-lg secondary_layout__sidebar">
<div className="h-full flex flex-col justify-between items-center">
<Link to="/"><h1 className="font-pacifico text-white px-2.5 py-1 bg-blue-700 rounded-full text-xl -mb-5">P</h1></Link>
<div className="flex flex-col space-y-2">
<NavLink to="/user/dashboard" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><TemplateIcon className="inline w-4 h-4 -mt-1"/></NavLink>
<NavLink to="/user/listings" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><ViewListIcon className="inline w-4 h-4 -mt-1"/></NavLink>
<NavLink to="/user/address" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><LocationMarkerIcon className="inline w-4 h-4 -mt-1"/></NavLink>
<NavLink to="/user/profile" className="px-2.5 py-1.5 rounded-lg shadow-md" activeClassName="bg-blue-700 shadow-lg text-white"><CogIcon className="inline w-4 h-4 -mt-1"/></NavLink>
</div>
<Avatar name={user.username} image={user.image} />
</div>
</div>
);
};
The sidebar has a css animation, and 3 NavLinks, every time I click on a link, the css animation restarts, the behavior that I want is the sidebar to only fade in once, and stay fixed even when I click on a navlink, I tried to wrap my sidebar component with React.memo() but that didn't fix the issue
Edit:
Let's say the user navigates to /user/dashboard, or /user/profile, all these routes should always render the sidebar
Example
Dashboard.js
import React from 'react';
import { Helmet } from 'react-helmet';
import SecondaryLayout from '../../layouts/SecondaryLayout';
const Dashboard = () => {
return (
<SecondaryLayout>
<Helmet>
<title>My Dashboard</title>
</Helmet>
Dashboard
</SecondaryLayout>
);
};
export default Dashboard;
I think I managed to fix the issue, what I was doing is to wrap every component by the secondary layout, what I have done is to move the Secondary Layout to wrap around the route component itself, and not around the component being rendered by the route, i.e: <Route .... /></Route .... />
I'm trying to use tailwindcss to create a collapsible card component similar to the pre-made component in Material-UI (reference).
I'm new to tailwindcss and can't quite figure out how to make the transition smooth. I have toggled the card using state.
The I am having trouble with is underneath the 'Image' component.
import Image from "next/image";
import { useRouter } from "next/router";
import { useState } from "react";
import { ChevronDownIcon } from "#heroicons/react/solid";
const ProjectCard = ({
title,
descriptionStart,
descriptionFull,
link,
image,
}) => {
const router = useRouter();
const [readMore, setReadMore] = useState(false);
return (
<div className='relative shadow-md flex flex-col bg-white rounded-lg p-4 m-4 space-y-8'>
<h1>{title}</h1>
<Image
src={image}
alt={title}
height={100}
width={100}
objectFit='contain'
/>
<div className='transition-all duration-200 ease-in-out'>
<p>{descriptionStart}</p>
<p
className={` ${
readMore
? "inline-flex transition-all ease-in-out duration-150"
: " hidden transition-all ease-in-out duration-150"
} `}>
{descriptionFull}
</p>
</div>
<button
className='bg-gray-100 w-[150px] h-[30px] rounded-lg shadow-lg mx-auto'
onClick={() => router.push(`${link}`)}>
View Project
</button>
<button
onClick={() => setReadMore(!readMore)}
className='absolute bottom-[16px] right-[16px]'>
{readMore ? (
<ChevronDownIcon className='rotate-180 h-6 transition-all duration-150 ease-in' />
) : (
<ChevronDownIcon className='h-6 transition-all duration-150 ease-in' />
)}
</button>
</div>
);
};
export default ProjectCard;