Logout link in React using Hooks - reactjs

I am using a simple boolean flag to set whether a user is logged in or out to do conditional rendering. I have doubled down with this flag to use it also as a way to logout. I am getting a TypeError that is saying my setIsLoggedIn is not a function, however I am using it in a similar way in another area of my program.
App.js :
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<div className="App">
<Switch>
<Route
path="/login"
render={() => (
<Login
isLoggedIn={isLoggedIn}
setIsLoggedIn={setIsLoggedIn}
/>
)}
/>
</Switch>
</div>
);
A portion of the code for SignedInLinks component:
const SignedInLinks = ({ isLoggedIn, setIsLoggedIn }) => {
const handleLogout = (e) => {
e.preventDefault();
setIsLoggedIn(false);
}
return (
<li><NavLink to='/login' onClick={handleLogout}>Logout</NavLink>
</li>
)
The error is exactly 'TypeError: setIsLoggedIn is not a function'

Define handleLogout in App.js
const handleLogout = (e) => {
e.preventDefault();
setIsLoggedIn(false);
}
return (
<div className="App">
<Switch>
<Route
path="/login"
render={() => (
<Login
isLoggedIn={isLoggedIn}
handleLogout={handleLogout}
/>
)}
/>
</Switch>
</div>
);

Sample Application of Login/Logout using Hooks
Hooks.js
function Hooks() {
const [loggedIn, setLoggedIn] = React.useState(false);
const handleClick = e => {
setLoggedIn(!loggedIn);
};
return (
<div>
{loggedIn ? (
<SignOut handleClick={handleClick} />
) : (
<SignIn handleClick={handleClick} />
)}
</div>
);
}
export default Hooks;
SignIn.js
function SignIn(props) {
return (
<div>
<h3>Please signin</h3>
<button onClick={props.handleClick}>signin</button>
</div>
);
}
SignOut.js
function SignOut(props) {
return (
<div>
<h3>Yay....You are loggedin</h3>
<button onClick={props.handleClick}>signout</button>
</div>
);
}

Related

How to correctly redirect after the user clicked logout

the app function have a router and i well use them in the components thanks for help ....
function App() {
return (
<Router>
<div className='App'>
<Switch>
<Route exact path='/'>
<Login />
</Route>
<Route path='/SignUp'>
<SignUp />
</Route>
</Switch>
<Route
path='/Student/:id'
exact
render={({ match }) => <Student match={match} />}
/>
<Route
path='/Admin/:id'
exact
render={({ match }) => <Admin match={match} />}
/>
</div>
</Router>
);
}
export default App;
just need to use redirect after the admin decided to click on the logout button
without using usehistory.
const Admin = () => {
const logoutfunc = async () => {
let connectToServer = new ConnectToServer();
//let session=await connectToServer.getSession()
connectToServer.logout();
};
const redirect = () => {
return <Redirect to={{ pathname: '/' }} />;
};
return (
<div>
<button
onClick={() => {
logoutfunc();
redirect();
}}
>
logout
</button>
<Cards />
<TableStudent />
<Cohorts />
</div>
);
};
export default Admin;
what you have to do is this:
const Admin = () => {
const [redirect, setRedirect] = useState(false);
const logoutfunc = async () => {
let connectToServer = new ConnectToServer();
//let session=await connectToServer.getSession()
connectToServer.logout();
setRedirect(true);
};
if(redirect){
return <Redirect to={{ pathname: '/' }} />;
};
return (
<div>
<button
onClick={logoutfunc}
>
logout
</button>
</div>
);
};
or use push method like this:
const Admin = () => {
const logoutfunc = async () => {
let connectToServer = new ConnectToServer();
//let session=await connectToServer.getSession()
connectToServer.logout();
history.push({ pathname: '/' })
};
return (
<div>
<button
onClick={logoutfunc}
>
logout
</button>
</div>
);
};

Error triggering a Link hook using react-router-v6

I'm updating a sourcecode from react-router-5 to version 6. So far I'm getting this error:
Error: [div] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
The bug is triggered when I activate a link in this component(QuoteItem.js):
const QuoteItem = (props) => {
return (
<li className={classes.item}>
<figure>
<blockquote>
<p>{props.text}</p>
</blockquote>
<figcaption>{props.author}</figcaption>
</figure>
<div className={classes.item}>
<Link className='btn' to={`/quotes/${props.id}`}>View Fullscreen</Link>
</div>
</li>
);
};
in another component (VerQuotes) I defined the routes:
const VerQuotes = () => {
return (
<div>
<main>
<Layout>
<Routes>
<Route path="quotes" element={<AllQuotes />} />
<Route path="new-quote" element={<NewQuote />} />
<Route path="quotes/:quoteId" element={<QuoteDetail />} />
</Routes>
</Layout>
</main>
</div>
);
};
I'm kind of lost how to tackle the error, your comments will be highly appreciated.
Thanks a lot
Update
QuoteDetail
const QuoteDetail = () => {
const match = useNavigate();
const params = useParams();
const { quoteId } = params;
const { sendRequest, status, data: loadedQuote, error } = useHttp(getSingleQuote, true);
//const quote = DUMMY_NOTES.find((quote) => quote.id === params.quoteId);
useEffect(() => {
sendRequest(quoteId);
}, [sendRequest, quoteId]);
if(status === "pending"){
return (
<div className="centered">
<LoadingSpinner />
</div>
);
}
if(error){
return <p className="centered">{error}</p>;
}
if (!loadedQuote.text) {
return <p>No Quote Found!</p>;
}
return (
<Fragment>
<HighlightedQuote text={loadedQuote.text} author={loadedQuote.author} />
<Routes>
<Route path={match}>
<div className="centered">
<Link
className="btn--flat"
to={`${match}/comments`}
>
Load Comments
</Link>
</div>
</Route>
<Route path={`${match}/comments`} element={<Comments />}></Route>
</Routes>
</Fragment>
);
};
Issues
After tracing your code I found you had a couple issues in QuoteDetail component.
You used const match = useNavigate(); (so match is really the navigate function) but then later used match to attempt to form a path string for a Route.
The Route component's children prop is only for rendering nested routes. The error you see is the use of the div element that isn't a Route component.
Code
<Routes>
<Route path={match}>
<div className="centered">
<Link
className="btn--flat"
to={`${match}/comments`}
>
Load Comments
</Link>
</div>
</Route>
<Route path={`${match}/comments`} element={<Comments />}></Route>
</Routes>
Solution
Remove const match = useNavigate(); since it is not used, and place the div into the element prop of the Route. Change the path props to use relative routing from the current route path that's already been built up.
const QuoteDetail = () => {
const params = useParams();
const { quoteId } = params;
const { sendRequest, status, data: loadedQuote, error } = useHttp(
getSingleQuote,
true
);
//const quote = DUMMY_NOTES.find((quote) => quote.id === params.quoteId);
useEffect(() => {
sendRequest(quoteId);
}, [sendRequest, quoteId]);
if (status === "pending") {
return (
<div className="centered">
<LoadingSpinner />
</div>
);
}
if (error) {
return <p className="centered">{error}</p>;
}
if (!loadedQuote.text) {
return <p>No Quote Found!</p>;
}
return (
<Fragment>
<HighlightedQuote text={loadedQuote.text} author={loadedQuote.author} />
<Routes>
<Route
path="/"
element={
<div className="centered">
<Link className="btn--flat" to="comments">
Load Comments
</Link>
</div>
}
/>
<Route path="comments" element={<Comments />} />
</Routes>
</Fragment>
);
};

Private Route is not rendering About Component

so I have the private routes set up in App.js. The other components in the private routes render correctly. The About Component isnt rendering. Before I was getting an error saying something along the lines of expected a string but got an object. Now I can goto the about page and the error is gone. I console.log props and slides but it doesnt show up in the console. I am passing props(slides) in the Private route to About.js.
Hi. Ive been stuck on this for two days now. PRivate route doesnt show the About component. It works on all other components. Code is below.Any help is greatly appreciated.
function App() {
return (
<div className="App">
<Nav/>
<main>
<Switch>
<PrivateRoute exact path="/home" component={Home} />
<PrivateRoute path="/resources" component={Resources} />
<PrivateRoute path = "/about" component={ About} slides= {SliderData} />
<PrivateRoute path="/mealplan" component={MealPlan} />
</Switch>
<Route exact path="/" component={SignUp} />
<Route path="/login" component={Login} />
</main>
</div>
);
}
export default App;
function About(slides) {
const [current, setCurrent] = useState(0);
const length = slides.length
if (!Array.isArray(slides) || slides.length <= 0) {
return null;
}
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
return (
<>
<section className="slider">
<FaArrowAltCircleLeft onClick={prevSlide} className="left-arrow" />
<FaArrowAltCircleRight onClick={nextSlide} className="right-arrow" />
{SliderData.map((slide, index) => {
return (
<div className={index === current ? "slide-active" : "active"} key={index}
>
{index === current && (
<img src={slide.image} alt="dog" className="dog-img" />
)}
</div>
);
})}
</section>
</>
Private Route
const PrivateRoute = ({component: Component, ...rest}) => {
return(<Route {...rest} render={
(props) => {
if (localStorage.getItem("token")) {
return <Component {...props}/>;
} else {
return(<Redirect to='/login'/>);
}
}
}/>);
};
Like I said it works on the other components but not the About Component. I have tried everything I can think of but cant get it to render
The issue is that you are trying to pass additional props through PrivateRoute to the component but don't pass them all the way through. You only pass the route props through.
PrivateRoute
const PrivateRoute = ({ component: Component, ...rest }) => {
return(
<Route
{...rest}
render={
(props) => {
if (localStorage.getItem("token")) {
return <Component {...props}/>; // <-- only route props from `render`
} else {
return(<Redirect to='/login'/>);
}
}}
/>
);
};
Refactor the PrivateRoute so it renders more like a plain Route component.
const PrivateRoute = (props) => {
return localStorage.getItem("token") ? (
<Route {...props} />
) : (
<Redirect to='/login'/>
);
};
Now use the render prop to render the About component and pass the additional prop(s) through.
function App() {
return (
<div className="App">
<Nav/>
<main>
<Switch>
<PrivateRoute exact path="/home" component={Home} />
<PrivateRoute path="/resources" component={Resources} />
<PrivateRoute
path="/about"
render={props => (
<About {...props} slides= {SliderData} />
)}
/>
<PrivateRoute path="/mealplan" component={MealPlan} />
</Switch>
<Route exact path="/" component={SignUp} />
<Route path="/login" component={Login} />
</main>
</div>
);
}
Ensure you are accessing the slides prop correctly. I.E. props.slides.
function About({ slides }) {
const [current, setCurrent] = useState(0);
const length = slides.length
if (!Array.isArray(slides) || slides.length <= 0) {
return null;
}
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
return (
<>
<section className="slider">
<FaArrowAltCircleLeft onClick={prevSlide} className="left-arrow" />
<FaArrowAltCircleRight onClick={nextSlide} className="right-arrow" />
{SliderData.map((slide, index) => {
return (
<div className={index === current ? "slide-active" : "active"} key={index}
>
{index === current && (
<img src={slide.image} alt="dog" className="dog-img" />
)}
</div>
);
})}
</section>
</>
);
}

Getting error SyntaxError: Missing semicolon

Checked the code and cannot find where I need to put a semicolon.
Here is error.
Here is the code.
It should be like this
const Routes = (props) => ( ... )
It should be like this
const PropsPage = () => { return ( <h3>Props Page</h3> );};
for a
const App = () => {
return (
<section className="App">
<Router>
...
<Link to="/404-not-found">404</Link>
<Link to="/props">Passing Props</Link> <Switch>
...
<Route exact path="/props" component={PropsPage} /> <Route component={NoMatchPage} />
</Switch>
</Router>
about with browser reload
</section>
);
};
Passing function as a component props in Route component
const PropsPage = ({ title }) => {
return (
<h3>{title}</h3>
);
};

Single page With React Router V6

Hello I am trying to make a react single page using the react router v 6, but I have the following error:
TypeError
Cannot read property 'location' of undefined
and I'm also not able to imagine the logic of how to do this basically I just want to change my ContentOne to ContentTwo
code:
export default function App() {
return (
<Router>
<route />
</Router>
);
}
Routes:
export default function MainRoutes() {
return (
<Routes>
<MainWrapper>
<Route path="/" element={<Header />} />
<Route path="/" element={<ContentOne />} />
<Route path="/contenttwo" element={<ContentTwo />} />
<Route path="/" element={<Footer />} />
</MainWrapper>
</Routes>
);
}
Header:
const Render = () => {
const history = useHistory();
return (
<Header>
<button onClick={() => history.push("/")}>ContentOne</button>
<button onClick={() => history.push("/contenttwo")}>ContentTwo</button>
</Header>
);
};
export default Render;
contentOne:
const Render = () => {
return <ContentOne />;
};
export default Render;
contentTwo:
const Render = () => {
return <ContentTwo />;
};
export default Render;
Footer:
const Render = () => {
return <Footer />;
};
export default Render;
example:
https://codesandbox.io/s/sad-paper-ps1vw

Resources