How to prevent protected route re rendering? - javascript

import React, { useContext } from "react";
import { useLocation } from "react-router";
import { Navigate, Outlet } from "react-router-dom";
function ProtectedRoute({ children }) {
const location = useLocation();
const user = sessionStorage.getItem("userDetails");
console.log(location)
return user? (
children
) : (
<Navigate
to="/login"
replace
state={{
from: location,
}}
/>
);
}
export default ProtectedRoute;
The above code is for the protected route
import React, { useContext, useState } from "react";
import "./login.css";
import Image from "../../assests/images/login-image.jpeg";
import Person from "#mui/icons-material/Person";
import RemoveRedEyeSharp from "#mui/icons-material/RemoveRedEyeSharp";
import VisibilityOffSharp from "#mui/icons-material/VisibilityOffSharp";
import ArrowBackSharp from "#mui/icons-material/ArrowBackSharp";
import { UserDetails } from "../../App";
import { motion } from "framer-motion";
import FormError from "../formError/FormError";
import { HashLoader } from "react-spinners";
import baseUrl from "../../config/BaseUrl";
import axios from "axios";
import { useLocation, useNavigate, Link } from "react-router-dom";
function Login() {
const [showPassword, setShowPassword] = useState(false);
const [showError, setShowError] = useState(false);
const [userDetails, setUserDetails] = useContext(UserDetails);
const location = useLocation();
const navigate = useNavigate();
const [userForm, setUserForm] = useState({
username: "",
password: "",
});
const [message, setMessage] = useState("Default");
const [theme, setTheme] = useState("None");
const [loading, setLoading] = useState(false);
const handleShowPassword = () => {
setShowPassword(!showPassword);
};
const handleChange = (e) => {
const { name, value } = e.target;
setUserForm({ ...userForm, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const response = await axios.post(`${baseUrl}/user/login`, userForm);
sessionStorage.setItem("userDetails", JSON.stringify(response.data.user));
sessionStorage.setItem("token", JSON.stringify(response.data.token));
setUserDetails(response.data.user);
if(location.state?.from){
navigate(location.state.from)
}
else{
navigate("/")
}
setLoading(false);
} catch ({ response }) {
setMessage(response.data.message);
setTheme("loginError");
setShowError(true);
setLoading(false);
}
};
return (
<motion.div
className="loginBackground"
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: {
duration: 0.15,
},
}}
exit={{
opacity: 0,
transition: {
duration: 0.15,
},
}}
>
<div className="loginForm">
{loading && (
<div className="loginLoading">
<HashLoader
color="#002db3"
loading={loading}
size={100}
></HashLoader>
</div>
)}
{!loading && (
<form className="loginFormInputs" onSubmit={handleSubmit}>
<div className="loginBack">
<ArrowBackSharp
style={{ fontSize: "1.7rem", cursor: "pointer" }}
onClick={() => navigate("/")}
></ArrowBackSharp>
</div>
<div className="loginFormHeader">
<div className="loginFormTitle">Welcome Back</div>
<div className="loginFormSubHeading">
Please login to your account to dive deep inside
</div>
</div>
<div className="loginFormInput">
<input
type="text"
name="username"
className="loginInput"
placeholder="Email"
required={true}
value={userForm.username}
onChange={handleChange}
/>
<Person></Person>
</div>
<div className="loginFormInput">
<input
type={showPassword ? "text" : "password"}
name="password"
className="loginInput"
spellCheck={false}
placeholder="Password"
required={true}
value={userForm.password}
onChange={handleChange}
/>
{showPassword ? (
<RemoveRedEyeSharp
onClick={handleShowPassword}
style={{ cursor: "pointer" }}
/>
) : (
<VisibilityOffSharp
onClick={handleShowPassword}
style={{ cursor: "pointer" }}
/>
)}
</div>
<div className="loginFormSubmit">
<button className="loginFormButton" type="submit">
Dive Deep
</button>
</div>
{showError && (
<FormError theme={theme} message={message}></FormError>
)}
<div className="loginFormSignUp">
Don't have an account?{" "}
<Link to={"/register"} style={{textDecoration:"none"}}>
<span
style={{
cursor: "pointer",
color: "blue",
fontWeight: "600",
fontSize: "1.1rem",
}}
>
Signup
</span>
</Link>
</div>
</form>
)}
<img src={Image} alt="img" className="loginImage" />
</div>
</motion.div>
);
}
export default Login;
This is the code snippet for the login component where the handle submit function is handling the redirect. Why is the protected route re-rendering twice? I tried removing the hooks and using session storage but still the protected route rendered twice and I can't understand why

Related

onLogin is not a function

I am making an app using react and ruby-on-rails. My issue is, when I use the commented out if statement (in App.js: line 31) everything works. However, when I try to use if statemen with expression (line 31), browser respond, that neither onLogin and onSignup is not a function.
App.js
import './App.css';
import HomePage from './HomePage'
import Feed from './Feed'
import Login from "./Login";
import Post from "./Post";
import Signup from './Signup';
import { Routes, Route } from "react-router-dom";
import { useState, useEffect } from 'react';
import NavBar from './NavBar';
import SearchUser from './SearchUser'
import UserPage from './UserPage'
function App() {
const [user, setUser] = useState(false) /* log in method */
const [search, setSearch] = useState([])
const [signup, setSignup] = useState(false)
useEffect(() => {
// auto-login
fetch("/me").then((r) => {
if (r.ok) {
r.json().then((user) => {
setUser(user)});
}
});
}, []);
if (!user) return(signup ? <Signup onSignup={setSignup}/> : <Login onLogin={setUser} onSignup={setSignup}/>);
// if (!user) return(<Login onLogin={setUser} />);
return (
<div className="App">
<NavBar user={user} onLogin={setUser} onSearch={setSearch} ></NavBar>
{search.length > 0 && <SearchUser users={search} clearSearch={setSearch}></SearchUser>}
<Routes>
<Route path="/feed" element={<Feed user={user}/>}></Route>
<Route path="/" element={<HomePage user={user} onLogin={setUser}/>}></Route>
<Route path="/signup" element={<Signup />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/posts/:id" element={<Post />}></Route>
<Route path="/users/:id" element={<UserPage userId={user.id} searched = {search} />}></Route>
</Routes>
</div>
);
}
export default App;
Login.js
import logo from './logo.svg';
import { useState } from 'react';
import { Link } from 'react-router-dom';
function Login({onLogin, onSignup}) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [errors, setErrors] = useState([])
function handleSubmit(e) {
e.preventDefault();
fetch("/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
}),
})
.then((r) => {
if(r.ok) {
setErrors([])
r.json().then((user) => {
onLogin(user)
console.log(`User: ${user.username} with id: ${user.id} has been logged in`)})
}
else {
r.json().then((err)=> setErrors(err.errors))
}
});
}
return(
<div className = "Login">
<header style={{display: "flex", flexDirection: "column", padding: "100px 500px"}}>
<section><img src={logo} style={{height: "50px", width: "50px"}} alt=""></img>Instaclone</section>
<form
onSubmit={handleSubmit}
style={{display: "flex", flexDirection: "column", margin: "50px 50px"}}>
{/* fetch error handlers for login and signup */}
{errors ?
<p>{errors}</p> :
<p></p>}
{/* fetch error handlers for login and signup */}
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}>
</input>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}>
</input>
<button type='submit'>login</button>
<button onClick={()=>onSignup(true)}><Link to="/signup">Don't have an account?</Link></button>
</form>
</header>
</div>
);
}
export default Login;
Signup.js
import logo from './logo.svg';
import { useState } from 'react';
import { Link } from 'react-router-dom';
function Signup({onSignup}) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [passwordConfirmation, setPasswordConfirmation] = useState("");
const [errors, setErrors] = useState([])
function handleSubmit(e) {
e.preventDefault();
fetch("/signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
password_confirmation: passwordConfirmation,
}),
})
.then((r) => {
if(r.ok) {
r.json().then((user) => {
onSignup(false)
console.log(`User: ${user.username} has been created`)})
}
else {
r.json().then((err)=> setErrors(err.errors))
}
});
}
return(
<div className = "Signup">
<header style={{display: "flex", flexDirection: "column", padding: "100px 500px"}}>
<section><img src={logo} style={{height: "50px", width: "50px"}} alt=""></img>Instaclone</section>
<form
onSubmit={handleSubmit}
style={{display: "flex", flexDirection: "column", margin: "50px 50px"}}>
{/* fetch error handlers for login and signup */}
{errors.length > 0 ?
errors.map((error, index)=><p key={index}>{error}</p>) :
<p></p>}
{/* fetch error handlers for login and signup */}
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}>
</input>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}>
</input>
<label htmlFor="password_confirmation">Confirm Password:</label>
<input
type="password"
id="password_confirmation"
value={passwordConfirmation}
onChange={(e) => setPasswordConfirmation(e.target.value)}>
</input>
<button type='submit'>Signup</button>
<button onClick={()=>onSignup(false)}><Link to="/login">I have an account!</Link></button>
</form>
</header>
</div>
);
}
export default Signup;
I think the problem is an expression that I used. However, I am not sure what might be the case as I am not getting any errors except the ones mentioned.
enter image description here
I tried to use the old statement I was using and surprisingly it works

when I go to Auth page it shows blank page due to Error

In my website that I'm making when I try to go to Authpage it shows error Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator)) in my signup.js
import React, { useState } from "react";
import { Button } from "#mui/material";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { useContext } from "react";
import { UserContext } from "./Context";
import { initializeApp } from "#firebase/app";
import {
getAuth,
RecaptchaVerifier,
signInWithPhoneNumber,
} from "firebase/auth";
import { signup } from "../../Actions/Auth";
import "./Auth.css";
function SignUpCard({ toggleCardFunc }) {
var firebaseConfig = {
apiKey: "*****",
authDomain: "*****",
projectId: "*****",
storageBucket: "******",
messagingSenderId: "******",
appId: "********",
measurementId: "*******",
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const [isLogin, setIsLogin] = useContext(UserContext); #here get error in this line on isLogin
const [checked, setchecked] = useState(false);
const [OTP, setOTP] = useState("");
const [displayOtp, setDisplayOTP] = useState(false);
const [user, setUser] = useState({
name: "",
email: "",
password: "",
});
const navigate = useNavigate();
const dispatch = useDispatch();
const handleCred = (e) => {
let name = e.target.name;
let value = e.target.value;
setUser({ ...user, [name]: value });
};
const configureRecaptcha = () => {
window.recaptchaVerifier = new RecaptchaVerifier(
"sign-in-button",
{
size: "invisible",
callback: (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
handleLogin();
console.log("Captcha Verified ");
},
defaultCountry: "IN",
},
auth
);
};
const handleLogin = () => {
const phoneNumber = "+91" + user?.phoneNo;
console.log(phoneNumber);
configureRecaptcha();
const appVerifier = window.recaptchaVerifier;
signInWithPhoneNumber(auth, phoneNumber, appVerifier)
.then((confirmationResult) => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
window.confirmationResult = confirmationResult;
console.log("OTP has been sent");
setDisplayOTP(true);
})
.catch((error) => {
console.log(error);
});
};
const validateOTP = () => {
if (OTP.length !== 6) return;
window.confirmationResult.confirm(OTP).then((result) => {
// User signed in successfully.
const userResult = result.user;
// console.log(JSON.stringify(userResult))
alert("User is verified");
dispatch(signup(user));
setIsLogin(true);
navigate("/");
});
};
return (
<div className="auth">
{!displayOtp ? (
<div className="authWrap">
<div>
<p>Display Name</p>
<input type="text" onChange={handleCred} name="name" />
</div>
<div>
<p>Email</p>
<input type="email" onChange={handleCred} name="email" />
</div>
<div>
<p>Phone No</p>
<input type="text" onChange={handleCred} name="phoneNo" />
</div>
<div>
<p>Password</p>
<input type="password" onChange={handleCred} name="password" />
</div>
<div className="tc">
<input
type="checkbox"
name="tc"
onChange={() => setchecked(!checked)}
checked={checked}
/>
<p>
Opt-in to receive occasional product updates, user research
invitations, company announcements, and digest.
</p>
</div>
<div id="sign-in-button"></div>
<div className="login-button">
{user.name !== "" &&
user.email !== "" &&
user.password !== "" &&
checked ? (
<Button
onClick={handleLogin}
style={{
marginTop: "1.5rem",
height: "2.3rem",
background: "#0a95ff",
boxShadow: "inset 0 1px 0 0 hsl(0deg 0% 100% / 40%)",
color: "white",
fontSize: "0.813rem",
textTransform: "capitalize",
}}
>
Sign Up
</Button>
) : (
<Button
disabled
style={{
marginTop: "1.5rem",
height: "2.3rem",
background: "#868686",
boxShadow: "inset 0 1px 0 0 hsl(0deg 0% 100% / 40%)",
color: "white",
fontSize: "0.813rem",
textTransform: "capitalize",
}}
>
Sign Up
</Button>
)}
</div>
</div>
) : (
<div>
<p>Enter OTP send to {user?.phoneNo}</p>
<input
type="password"
onChange={(e) => setOTP(e.target.value)}
name="name"
/>
<div className="login-button">
<Button
onClick={validateOTP}
style={{
marginTop: "1.5rem",
height: "2.3rem",
background: "#0a95ff",
boxShadow: "inset 0 1px 0 0 hsl(0deg 0% 100% / 40%)",
color: "white",
fontSize: "0.813rem",
textTransform: "capitalize",
}}
>
Submit OTP
</Button>
</div>
</div>
)}
<div className="login-signup">
<p>
Already have an account?{" "}
<span style={{ cursor: "pointer" }} onClick={toggleCardFunc}>
Log in
</span>
</p>
<p>
{" "}
Are you an employer? <span> Sign up on Talent </span>
</p>
</div>
</div>
);
}
export default SignUpCard;
And here context.js which I'm importing
import { useState, createContext } from "react";
export const UserContext = createContext();
export const UserProvider = ({ children }) => {
const [isLogin, setIsLogin] = useState(false);
return (
<UserContext.Provider value={[isLogin, setIsLogin]}>
{children}
</UserContext.Provider>
);
};
I have tried to put what was suggested by vscode above the line that gives error
// eslint-disable-next-line no-unused-vars
const [isLogin, setIsLogin] = useContext(UserContext);
but still getting the same error ------- Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator)) in both login.js and signup.js at the same lineyour text
Then I tried to comment the line and got the page but can't able to login because of commentting the line
can please someone help and tell what the issue is so that my code can work I'm just getting blank page right now with the above issue please someone suggest something provide answer
You are getting this error because you didn't wrap your components inside UserProvider. You can do that for example in index.js after importing it at the top, like so:
import {UserProvider} from "./path/context"; // ⚠️ use the correct path
...
root.render(
<Provider store={store}>
<React.StrictMode>
<UserProvider>
<App />
</UserProvider>
</React.StrictMode>
</Provider>
);

Products Update using Redux When click on " Category" name one Mega Menu, MegaMenu And Product both are different components

Please See the >>
I want to update Products by clicking on Category Name the MegaMenu, But it does not change. I use redux for state management. Please help me !!
This is MegaMenu Component
import MenuIcon from '#mui/icons-material/Menu';
import './MegaMenu.css';
import { NavLink } from 'react-router-dom';
import ArrowRightIcon from '#mui/icons-material/ArrowRight';
const categories = [
"Sunglass",
"Footwear",
"Men Watch",
"Women Watch",
"Computer",
"SmartPhones",
"Camera",
];
const MegaMenu = () => {
return (
<div className='mega_menu_component'>
<div className='mega_menu_Items'>
<div className='mega_menus'>
<MenuIcon className='mega_menu_icon' style={{ fontSize: '40px', color: '#fff', cursor: 'pointer' }} />
<div class="menu_link_content">
<NavLink className="menu_name" to="/">Home</NavLink>
<NavLink className="menu_name" to="/products">Shop <ArrowRightIcon style={{ fontSize: 'medium' }} />
<ul className="categoryMenu">
{categories.map((categoryName) => (
<li className="categoryMenu-link" > <NavLink style={{ textDecoration: 'none', color: '#000' }} key={categoryName} to={`/products/${categoryName}`}>{categoryName}</NavLink></li>
))}
</ul>
</NavLink>
<NavLink className="menu_name" to="/contact">Contact</NavLink>
<NavLink className="menu_name" to="/about">About</NavLink>
</div>
</div>
</div>
</div>
);
};
export default MegaMenu;
This is Products component
import React, { Fragment, useEffect, useState } from "react";
import "./Products.css";
import { useSelector, useDispatch } from "react-redux";
import { clearErrors, getProduct } from "../../actions/productAction";
import Loader from "../layout/Loader/Loader";
import ProductCard from "../Home/ProductCard";
import Pagination from "react-js-pagination";
import Slider from "#material-ui/core/Slider";
import { useAlert } from "react-alert";
import Typography from "#material-ui/core/Typography";
import MetaData from "../layout/MetaData";
import { useParams } from "react-router";
import { NavLink, useLocation } from "react-router-dom"
const categories = [
"Sunglass",
"Footwear",
"Men Watch",
"Women Watch",
"Computer",
"SmartPhones",
"Camera",
];
const Products = ({ match }) => {
const dispatch = useDispatch();
const urlLocation = useLocation();
const categoryName = urlLocation.pathname.split('/')[2];
const alert = useAlert();
const [currentPage, setCurrentPage] = useState(1);
const [price, setPrice] = useState([0, 25000]);
// const [category, setCategory] = useState(categoryName);
const [category, setCategory] = useState('');
const [ratings, setRatings] = useState(0);
const {
products,
loading,
error,
productsCount,
resultPerPage,
filteredProductsCount,
} = useSelector((state) => state.products);
const keyword = match.params.keyword;
const setCurrentPageNo = (e) => {
setCurrentPage(e);
};
const priceHandler = (event, newPrice) => {
setPrice(newPrice);
};
let count = filteredProductsCount;
useEffect(() => {
if (error) {
alert.error(error);
dispatch(clearErrors());
}
dispatch(getProduct(keyword, currentPage, price, category, ratings));
}, [dispatch, keyword, currentPage, price, category, ratings, alert, error]);
return (
<Fragment>
{loading ? (
<Loader />
) : (
<Fragment>
<MetaData title="PRODUCTS -- ECOMMERCE" />
<h2 className="productsHeading">Products</h2>
<div className="products">
{products &&
products.map((product) => (
<ProductCard key={product._id} product={product} />
))}
</div>
<div className="filterBox">
<Typography>Price</Typography>
<Slider
value={price}
onChange={priceHandler}
valueLabelDisplay="auto"
aria-labelledby="range-slider"
min={0}
max={25000}
/>
<Typography>Categories</Typography>
<ul className="categoryBox">
{categories.map((category) => (
<li className="category-link" >
<NavLink style={{ textDecoration: 'none', color: 'black' }} key={category} onClick={() => setCategory(category)} to={`/products`}>{category}</NavLink>
</li>
))}
</ul>
<fieldset>
<Typography component="legend">Ratings Above</Typography>
<Slider
value={ratings}
onChange={(e, newRating) => {
setRatings(newRating);
}}
aria-labelledby="continuous-slider"
valueLabelDisplay="auto"
min={0}
max={5}
/>
</fieldset>
</div>
{resultPerPage < count && (
<div className="paginationBox">
<Pagination
activePage={currentPage}
itemsCountPerPage={resultPerPage}
totalItemsCount={productsCount}
onChange={setCurrentPageNo}
nextPageText="Next"
prevPageText="Prev"
firstPageText="1st"
lastPageText="Last"
itemClass="page-item"
linkClass="page-link"
activeClass="pageItemActive"
activeLinkClass="pageLinkActive"
/>
</div>
)}
</Fragment>
)}
</Fragment>
);
};
export default Products;
** When I want to click on the mega menu "Shop>>Category" name the URL would be like http://localhost:3000/products/Sunglass Here sunglass is the category name **
** Now I want to data update in the Product component (ProductCard Update) using the URL category part. But it does not work. **

Why is always the first changed?

I can update a Note but if I update it it updates the first note which is in myPosts section.
I really don´t understand. If I click on a Note which I create then it goes to the site "/notesEdit" so and I can see there the current forumName and forumDescription but if I change it, it doesn´t change the current selected note instead the first in List.
Here are the Notes which the user sees which he has created :
import React, { useEffect } from "react";
import { Button, Accordion } from "react-bootstrap";
import { Link } from "react-router-dom";
import MainScreen from "../components/MainScreen";
import ReactMarkdown from "react-markdown";
import { useDispatch, useSelector } from "react-redux";
import { deleteNoteAction, listForumUser } from "../../redux/forum/noteActions";
function NotesMe({ history, search }) {
const dispatch = useDispatch();
const userLogin = useSelector((state) => state.userLogin);
const { userInfo } = userLogin;
const noteList = useSelector((state) => state.noteList);
const { notes } = noteList;
console.log(noteList);
const deleteHandler = (_id) => {
if (window.confirm("Are you sure?")) {
dispatch(deleteNoteAction(_id));
dispatch(listForumUser());
}
};
useEffect(() => {
dispatch(listForumUser());
}, [dispatch]);
return (
<MainScreen title={` ${userInfo.userName}´s Forum..`}>
<Link to="createForum">
<Button style={{ marginLeft: 10, marginBottom: 6 }} size="lg">
Create New Forum
</Button>
</Link>
{notes &&
notes.map((forum) => (
<Accordion key={forum._id} defaultActiveKey="0">
<Accordion.Item style={{ margin: 10 }} key={forum._id}>
<Accordion.Header style={{ display: "flex" }}>
<span
style={{
color: "black",
textDecoration: "none",
flex: 1,
cursor: "pointer",
alignSelf: "center",
fontSize: 18,
}}
>
{forum.forumName}
</span>
<div>
<Link
to={{
pathname: "/notesEdit",
query: { forum },
}}
>
<Button id="EditButton">Edit</Button>
</Link>
<Button
variant="danger"
className="mx-2"
onClick={() => deleteHandler(forum._id)}
>
Delete
</Button>
</div>
</Accordion.Header>
<Accordion.Body>
<blockquote className="blockquote mb-0">
<ReactMarkdown>{forum.forumDescription}</ReactMarkdown>
<footer className="blockquote-footer">
Created on{" "}
<cite title="Source Title">
{/* {forum.published_on && forum.published_on.substring(0, 300)} */}
{/* {forum.user.userName && forum.user.userName} */}
</cite>
</footer>
</blockquote>
</Accordion.Body>
</Accordion.Item>
</Accordion>
))}
</MainScreen>
);
}
export default NotesMe;
and this is the site where the user can change it :
import React, { useState, useEffect } from "react";
import { Form, Button, Row, Col } from "react-bootstrap";
import { useLocation } from "react-router";
import MainScreen from "../components/MainScreen";
import { useDispatch, useSelector } from "react-redux";
import { updateNoteAction } from "../../redux/forum/noteActions";
import "./NotesEdit.css";
const NotesEdit = ({ history }) => {
const [forumName, setforumName] = useState("");
const [forumDescription, setforumDescription] = useState("");
const { query } = useLocation();
const dispatch = useDispatch();
const userLogin = useSelector((state) => state.userLogin);
const { userInfo } = userLogin;
const noteList = useSelector((state) => state.noteList);
const { notes } = noteList;
useEffect(() => {
if (query) {
setforumName(query.forum.forumName);
setforumDescription(query.forum.forumDescription);
}
}, [query]);
const submitHandler = (e) => {
e.preventDefault();
dispatch(updateNoteAction({ forumName, forumDescription }));
};
return (
<MainScreen title="EDIT MyNote">
<div id="ForumEdit">
<Row className="ForumContainer">
<Col md={6}>
<Form onSubmit={submitHandler}>
<Form.Group controlId="forumName">
<Form.Label>forumName</Form.Label>
<Form.Control
id="forumNameInput"
type="text"
placeholder="Enter forumName"
value={forumName}
onChange={(e) => setforumName(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="forumDescription">
<Form.Label>forumDescription</Form.Label>
<Form.Control
id="forumDescriptionInput"
type="text"
placeholder="Enter forumDescription"
value={forumDescription}
onChange={(e) => setforumDescription(e.target.value)}
></Form.Control>
</Form.Group>
<Button
id="EditButton"
type="submit"
varient="primary"
onClick={submitHandler}
>
Update
</Button>
</Form>
</Col>
<Col
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
></Col>
</Row>
</div>
</MainScreen>
);
};
export default NotesEdit;
export const updateNoteAction = (forum) => async (dispatch, getState) => {
try {
dispatch({
type: NOTES_UPDATE_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const url = "http://localhost:8080/forum/";
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.put(url, forum, config);
dispatch({
type: NOTES_UPDATE_SUCCESS,
payload: data,
});
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
dispatch({
type: NOTES_UPDATE_FAIL,
payload: message,
});
}
};
const forumSchema = ({
forumName: {
type: String,
required: true,
},
forumDescription: {
type: String,
required: true,
},
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
published_on: {
type: String,
default: moment().format("LLL")
},
});

react link route not redirecting to url

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;
Navigator.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>
</Switch>
</div>
</Router>
);
}
}
function Home() {
return (
<div style={{ paddingTop: "20%", textAlign: "center" }}>
<h1>Home</h1>
</div>
);
}
export default Navigator;
when i hover on the<li> the bottom of the browser the path is showing currectly
i think the problem is here i tried another links here nothing is working here
<Link to={`/detiled/${suggestion.id}`}> //this link dont work
<li
style={styles.listyle}
// onMouseOver={{ background: "yellow" }}
key={index}
className={classname}
>
{suggestion.firstname}
</li>
</Link>
i tryed another link under the flowing code
a button called hello and that works i think the probelm is with the return
<SuggestionsList
inputValue={inputValue}
selectedSuggestion={selectedSuggestion}
onSelectSuggestion={onSelectSuggestion}
displaySuggestions={displaySuggestions}
suggestions={filteredSuggestions}
/>
<Link
to={{
pathname: `/detiled/5`,
}}
>
<button>hello</button>
</Link>
try using
<Route path="/detiled/:id" component={InnerDetail} />
instead of
<Route path="/detiled/:id">
<InnerDetail />`
in Navigator.js
and
Route exact path="/">
<Home />
did you created any Home component, and not imported that in Navigator.js
<Link to={"/detiled/"+ suggestion.id}><li>...</li></Link>
this worked for me

Categories

Resources