not able to route in react js - javascript

I have this serch.js file. When I search and click on the li in the search result, I want to get redirected to <InnerDetail /> but the URL doesn't change or I don't get redirected to this page
but manualy if I type in the URL localhost/detiled/8 I am redirected to to <InnerDetail /> with id as 8
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faSearch } from "#fortawesome/free-solid-svg-icons";
import { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useHistory } from "react-router-dom";
const initialState = {
idaddProducts: "",
};
const Searchclients = () => {
const history = useHistory();
const [showResults, setShowResults] = React.useState(true);
const [poName, pnName] = React.useState(initialState);
const [showSerch, setShowSerch] = React.useState([]);
const [detail, setDetail] = useState(false);
const [inputValue, setInputValue] = React.useState("");
const [filteredSuggestions, setFilteredSuggestions] = React.useState([]);
const [selectedSuggestion, setSelectedSuggestion] = React.useState(0);
const [displaySuggestions, setDisplaySuggestions] = React.useState(false);
const suggestions = [];
showSerch.forEach(function (data) {
suggestions.push(data);
});
const onChange = (event) => {
const value = event.target.value;
setInputValue(value);
setShowResults(false);
const filteredSuggestions = suggestions.filter(
(suggestion) =>
suggestion.firstname
.toString()
.toLowerCase()
.includes(value.toLowerCase()) ||
suggestion.id.toString().toLowerCase().includes(value.toLowerCase())
);
setFilteredSuggestions(filteredSuggestions);
setDisplaySuggestions(true);
};
const onSelectSuggestion = (index) => {
setSelectedSuggestion(index);
setInputValue(filteredSuggestions[index]);
setFilteredSuggestions([]);
setDisplaySuggestions(false);
};
const SuggestionsList = (props) => {
// console.log(props);
const {
suggestions,
inputValue,
onSelectSuggestion,
displaySuggestions,
selectedSuggestion,
} = props;
if (inputValue && displaySuggestions) {
if (suggestions.length > 0) {
return (
<ul className="suggestions-list" style={styles.ulstyle}>
{suggestions.map((suggestion, index) => {
// console.log(suggestions);
const isSelected = selectedSuggestion === index;
const classname = `suggestion ${isSelected ? "selected" : ""}`;
return (
<Link to={`/detiled/${suggestion.id}`}> //this link dont work
<li
style={styles.listyle}
// onMouseOver={{ background: "yellow" }}
key={index}
className={classname}
>
{suggestion.firstname}
</li>
</Link>
);
})}
</ul>
);
} else {
return <div>No suggestions available...</div>;
}
}
return <></>;
};
useEffect(() => {
axios
.get("all-doctors-list/")
.then((res) => {
const data = res.data;
// pnName(data.data);
// var stringdata = data;
setShowSerch(data);
//console.log(stringdata);
});
// setShowSerch(data);
}, []);
return (
<>
<div className="note-container" style={styles.card}>
<div style={styles.inner}>
<p style={{ textAlign: "left" }}>Search Doctors</p>
<form className="search-form" style={{}}>
{showResults ? (
<FontAwesomeIcon
style={{ marginRight: "-23px" }}
icon={faSearch}
/>
) : null}
<input
onChange={onChange}
value={inputValue}
style={styles.input}
type="Search"
/>
<SuggestionsList
inputValue={inputValue}
selectedSuggestion={selectedSuggestion}
onSelectSuggestion={onSelectSuggestion}
displaySuggestions={displaySuggestions}
suggestions={filteredSuggestions}
/>
</form>
</div>
</div>
</>
);
};
export default Searchclients;
nav.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import InnerDetail from "./client/doctor/components/innerto_detail.js";
class Navigator extends React.Component {
render() {
return (
<Router>
<div>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/detiled/:id">
<InnerDetail />
</Route>
</div>
</Router>
);
}
}
function Home() {
return (
<div style={{ paddingTop: "20%", textAlign: "center" }}>
<h1>Home</h1>
</div>
);
}
export default Navigator;

You are missing closing tag of Switch:
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import InnerDetail from "./client/doctor/components/innerto_detail.js";
class Navigator extends React.Component {
render() {
return (
<Router>
<div>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/detiled/:id">
<InnerDetail />
</Route>
</Switch>
</div>
</Router>
);
}
}
function Home() {
return (
<div style={{ paddingTop: "20%", textAlign: "center" }}>
<h1>Home</h1>
</div>
);
}
export default Navigator;
Also its a tipo but you may want to say detailed, instead of detiled, but that does not affect.

Related

When a button in React is clicked, the component renders twice

I'm pretty new to React, and I'm making an ecommerce website for practice. I have a cart component that dynamically renders cart items from an API, but I narrowed the problem 100% down to the front end. On the initial render, it works fine, everything that is in the database cart appears, however after I press the "Delete from Cart" button on a cart item, each cart item doubles.
CartCard.jsx
(/api/delete returns a json object of the cart AFTER deletion. deletion is handled in the api)
import React from "react";
import CartCardCSS from "./CartCard.module.css";
export default function CartCard(props) {
const passCart = props.passCart;
function deleteFromCart(e) {
e.preventDefault();
const item = {
id: props.id,
mainText: props.mainText,
price: props.price,
type: props.type
}
const user = {
username: props.username
}
const compoundEntity = {
theContent: item,
theUser: user
}
const requestOptions = {
method: "POST",
headers: {"Content-Type" : "application/json"},
body: JSON.stringify(compoundEntity)
}
fetch("/api/delete", requestOptions)
.then(response => response.json())
.then(response => {
passCart(response)
console.log(response)
})
}
return (
<div className={CartCardCSS.card}>
<img src={props.image} className={CartCardCSS.itempicture} alt="item picture"/>
<h3 className={CartCardCSS.subitem}>{props.mainText}</h3>
<h4 className={CartCardCSS.subitem}>{props.price}</h4>
<button onClick={deleteFromCart} className={`${CartCardCSS.subitem} ${CartCardCSS.button}`} type="button">Remove From Cart</button>
</div>
)
}
Cart.jsx:
import React, {useEffect, useState} from "react";
import CartCard from "./CartCard";
import CpuPicture from "./img/cpu.jpg";
import GpuPicture from "./img/gpu.jpg";
export default function Cart(props) {
const cart = props.cart;
const username = props.username;
const passCart = props.passCart;
const [arrCart, setArrCart] = useState(Object.values(cart))
const [cartComp, setCartComp] = useState()
useEffect(() => {
console.log(cart)
setArrCart(Object.values(cart))
for(let i = 0; i < arrCart.length; i++) {
setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={arrCart[i].mainText} price={arrCart[i].price} type={arrCart[i].type} image={arrCart[i].type === "cpu" ? CpuPicture : GpuPicture}/>])
}
}, [cart])
return (
<div>
<h2 >Cart:</h2>
{cartComp}
</div>
)
}
Profile.jsx:
import React from "react";
import Cart from "./Cart";
import Navbar from "./Navbar";
import {useNavigate} from "react-router-dom";
export default function Profile(props) {
const username = props.username;
const isLoggedIn = props.isLoggedIn;
const cart = props.cart;
const passCart = props.passCart;
let navigate = useNavigate();
const routeChange = () => {
let path = "/login";
navigate(path);
}
if (isLoggedIn) {
return (
<div>
<Navbar />
<h1>{username}</h1>
<Cart passCart={passCart} username={username} cart={cart} />
</div>
)
} else {
routeChange();
}
}
App.jsx
import React, {useState} from "react";
import './App.css';
import Login from "./components/Login";
import Signup from "./components/Signup";
import Home from "./components/Home";
import Profile from "./components/Profile";
import Card from "./components/Card";
import GpuPicture from "./components/img/gpu.jpg";
import CpuPicture from "./components/img/cpu.jpg";
import {BrowserRouter, Routes, Route, Navigate} from "react-router-dom";
function App() {
const [username, setUsername] = useState('');
const [cart, setCart] = useState('');
const [isLoggedIn, setIsLoggedIn] = useState(false)
function passUsername(items) {
setUsername(items);
}
function passCart(items) {
setCart(items);
}
function passIsLoggedIn(items) {
setIsLoggedIn(items);
}
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Navigate to="/login"/>} />
<Route path="/login" element={<Login passIsLoggedIn={passIsLoggedIn} passUsername={passUsername} passCart={passCart}/>}/>
<Route path="/signup" element={<Signup />}/>
<Route path="/home" element={<Home passCart={passCart} cart={cart} username={username} isLoggedIn={isLoggedIn} />} />
<Route path="/profile" element={<Profile passCart={passCart} cart={cart} username={username} isLoggedIn={isLoggedIn}/>} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
Thanks for your help
As #deaponn mentioned, useState is asynchronous.
Your for loop in setCartComp is called n times. Alternatively what about using javascript's map function:
useEffect(() => {
console.log(cart);
// map transforms the array into an array of another type (in this case CartCard instances)
setCartComp(Object.values(cart).map((item, index) =>
<CartCard key={index} id={index}
passCart={passCart}
username={username}
mainText={item.mainText}
price={item.price}
type={item.type}
image={item.type === "cpu" ? CpuPicture : GpuPicture} />));
}, [cart]);
This for loop might be the issue:
useEffect(() => {
console.log(cart)
setArrCart(Object.values(cart))
for(let i = 0; i < arrCart.length; i++) {
setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={arrCart[i].mainText} price={arrCart[i].price} type={arrCart[i].type} image={arrCart[i].type === "cpu" ? CpuPicture : GpuPicture}/>])
}
}, [cart])
Keep in mind that setState in react is asynchronous. What it means:
console.log(arrCart) // previous state
setArrCart(Object.values(cart))
console.log(arrCart) // still previous state
Try changing your for loop into that:
for(let i = 0; i < cart.length; i++) {
setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={cart[i].mainText} price={cart[i].price} type={cart[i].type} image={cart[i].type === "cpu" ? CpuPicture : GpuPicture}/>])
}

BrowserRouter not loading pages [duplicate]

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;

Referencing the state leads to "TypeError: Cannot read property 'folders' of undefined"

I want to add to a state array, but I find that any code I write that brings up the state leads to the same error one the browser tries to run it.
Even just a console.log triggers it.
var folderList = this.state.folders;
console.log("folderList: " + folderList);
The full code:
import React, {Component} from 'react';
import {Route, Link} from 'react-router-dom';
import {FontAwesomeIcon} from '#fortawesome/react-fontawesome';
import NoteListNav from '../NoteListNav/NoteListNav';
import NotePageNav from '../NotePageNav/NotePageNav';
import NoteListMain from '../NoteListMain/NoteListMain';
import NotePageMain from '../NotePageMain/NotePageMain';
import dummyStore from '../dummy-store';
import {getNotesForFolder, findNote, findFolder} from '../notes-helpers';
import './App.css';
import AddFolder from '../AddFolder/AddFolder';
import AddNote from '../AddNote/AddNote';
class App extends Component {
state = {
notes: [],
folders: [],
//noteID: 0,
//folderID: 0
};
componentDidMount() {
// fake date loading from API call
setTimeout(() => this.setState(dummyStore), 600);
}
folderSubmit(f){
console.log("folderSubmit ran " + f);
var folderList = this.state.folders;
console.log("folderList: " + folderList);
//this.setState({ folders: joined })
}
renderNavRoutes() {
const {notes, folders} = this.state;
return (
<>
{['/', '/folder/:folderId'].map(path => (
<Route
exact
key={path}
path={path}
render={routeProps => (
<NoteListNav
folders={folders}
notes={notes}
{...routeProps}
/>
)}
/>
))}
<Route
path="/note/:noteId"
render={routeProps => {
const {noteId} = routeProps.match.params;
const note = findNote(notes, noteId) || {};
const folder = findFolder(folders, note.folderId);
return <NotePageNav {...routeProps} folder={folder} />;
}}
/>
<Route path="/add-folder" component={NotePageNav} />
<Route path="/add-note" component={NotePageNav} />
</>
);
}
renderMainRoutes() {
const {notes, folders} = this.state;
return (
<>
{['/', '/folder/:folderId'].map(path => (
<Route
exact
key={path}
path={path}
render={routeProps => {
const {folderId} = routeProps.match.params;
const notesForFolder = getNotesForFolder(
notes,
folderId
);
return (
<NoteListMain
{...routeProps}
notes={notesForFolder}
/>
);
}}
/>
))}
<Route
path="/note/:noteId"
render={routeProps => {
const {noteId} = routeProps.match.params;
const note = findNote(notes, noteId);
return <NotePageMain {...routeProps} note={note} />;
}}
/>
<Route
path="/add-folder"
render={routeProps => {
return <AddFolder addNewFolder={this.folderSubmit}/>
}}
/>
<Route
path="/add-note"
render={routeProps => {
return <AddNote/>
}}
/>
</>
);
}
render() {
return (
<div className="App">
<nav className="App__nav">{this.renderNavRoutes()}</nav>
<header className="App__header">
<h1>
<Link to="/">Noteful</Link>{' '}
<FontAwesomeIcon icon="check-double" />
</h1>
</header>
<main className="App__main">{this.renderMainRoutes()}</main>
</div>
);
}
}
export default App;
this will not be what you expect inside of folderSubmit. How to get around this is discussed in the "Handling Events" part of the documentation. You could bind it to this in the constructor, or use an arrow function as a class field.
folderSubmit = (f) => {
var folderList = this.state.folders;
console.log("folderList:", folderList);
}

findDOMNode is deprecated in StrictMode React material UI

I am getting this error on my React material UI project
By looking at the error I guess it comes somewhere inside the Drawer.js component.
This is my full Drawer.js component
import React, { Fragment, useState } from "react";
import clsx from "clsx";
import { makeStyles, useTheme } from "#material-ui/core/styles";
import Drawer from "#material-ui/core/Drawer";
import { List, Collapse } from "#material-ui/core";
import Divider from "#material-ui/core/Divider";
import ListItem from "#material-ui/core/ListItem";
import IconButton from "#material-ui/core/IconButton";
import ListItemText from "#material-ui/core/ListItemText";
import { toggleDrawer } from "../../store/actions/authActions";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import ChevronLeftIcon from "#material-ui/icons/ChevronLeft";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
// import ClickAwayListener from '#material-ui/core/ClickAwayListener'
import { useHistory } from 'react-router-dom';
import { connect } from "react-redux";
import { withRouter } from "react-router";
const useStyles = makeStyles({
list: {
width: 250,
},
fullList: {
width: "auto",
},
});
function TemporaryDrawer(props) {
const classes = useStyles();
const theme = useTheme();
// const [open, setOpen] = React.useState(false);
const [openIndex, setOpenIndex] = useState(0);
let history = useHistory();
// const handleDrawerOpen = () => {
// setOpen(true);
// };
const handleDrawerClose = () => {
props.toggleDrawer();
};
const handleClick = (index) => {
if (openIndex === index) {
setOpenIndex(-1);
} else {
setOpenIndex(index);
}
};
const onToggle = () => (event) => {
if (
event.type === "keydown" &&
(event.key === "Tab" || event.key === "Shift")
) {
return;
}
props.toggleDrawer();
};
const onRoute = (path) => {
// props.history.push(path);
history.push(path);
props.toggleDrawer();
};
const list = (anchor) => (
<div
className={clsx(classes.list, {
[classes.fullList]: anchor === "top" || anchor === "bottom",
})}
role="presentation"
>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === "ltr" ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</div>
<Divider />
<List>
{props.permissions.map((route, index) => (
<Fragment key={index}>
<ListItem button onClick={(e) => handleClick(index)}>
<ListItemText primary={route.name} />
{index === openIndex ? <ExpandLess /> : <ExpandMore />}
</ListItem>
{route.children.length && (
<Collapse
in={openIndex === index ? true : false}
timeout="auto"
unmountOnExit
>
<List component="div" disablePadding>
{route.children.map((child, idx) => (
<ListItem
button
className={classes.nested}
key={idx}
onClick={() => onRoute(child.path)}
>
<ListItemText primary={child.name} />
</ListItem>
))}
</List>
<Divider />
</Collapse>
)}
</Fragment>
))}
</List>
{/* <Divider /> */}
</div>
);
return (
<div>
{props.token && (
<Drawer
anchor="left"
open={props.isDrawerOpen}
onClose={onToggle("left", false)}
variant="persistent"
>
{list("left")}
</Drawer>
)}
</div>
);
}
const mapStateToProps = (state) => {
return {
isDrawerOpen: state.auth.isDrawerOpen,
token: state.auth.token,
permissions: state.auth.routes,
};
};
export default withRouter(
connect(mapStateToProps, { toggleDrawer })(TemporaryDrawer)
);
I go through this error and some say this is a problem in MUI library and no way to fix this. But I believe there must be a workaround for this. This causes serious problems for UI.
Where this error comes from and what can I do to fix this?
Any help!
Thanks in advance. =)
I use material UI 4.11.0
and react 16
You only need to create a new childComponent with react.forwardRef passing respective props and refs:
const ChildComponent = React.forwardRef((props, ref) =>
<div ref={ref}>
<yourChildcomponent {...props} />
</div>
);
In your render change the name of the original Child for the new:
<ChildComponent... />

React scroll nav using useRef in seperate routes

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

Categories