Redirect react-router-dom v6 - reactjs

I have a problem, watching a video on youtube that used history.push('/login?redirect=shipping'), how can I modify it using navigate, because if I use the string navigate ('/ login?redirect=shipping') even if logged in it returns to home page and does not go to the shipping page.
I solved the problem in this way :
const checkoutHandler = () => {
if(!userInfo){
navigate('/login')
} else{
navigate('/shipping')
}
}

Your solution is good.
Can I fill in some gaps?
We need to get the state of user to check if user logged in to proceed with if statement.
After this your solution will work.
import React from 'react'
import { useNavigate } from 'react-router-dom'
import { useSelector } from 'react-redux'
//....some imports
const CartScreen = () => {
//.......some code before
const navigate = useNavigate()
const userLogin = useSelector((state) => state.userLogin)
const { userInfo } = userLogin
const checkoutHandler = () => {
if (!userInfo) {
navigate('/login')
} else {
navigate('/shipping')
}
}
//...return JSX...

**Try this one.
const navigate = useNavigate()
const checkoutHandler = () => {
navigate('/signin?redirect=/shipping')
}

Have you sort out this problem or not? If you are facing the same problem then I suggest you go on your login page and make some changing.
Import useHistory and useLocation:
import { Link, useHistory, useLocation } from 'react-router-dom'
Then in functions apply this:
const history = useHistory();
const location = useLocation();

Related

React Router Dom V6

What is the difference between Navigate component and navigate from useNavigate() hook?.
if (therapy !== desiredGroupTherapy || required.includes('admin') && !isAdmin) {
const pathname = generatePath(pageRoutes.DASHBOARD, {
groupId: desiredGroupId,
therapy: therapyForValidGroup,
})
navigate(pathname, { replace: true })
// return <Navigate to={pathname} replace />
}
I have issue with navigate here. How that should work: I redirect to that page, but at first time I have no therapy, so I should redirect to the same page but my therapy now will be equal to therapyForValidGroup. I have custom hook useTherapy() which takes therapy from URL. So at first time when it is undefined it crashes using navigate function. But using Navigate component, it works fine. So what is the difference?
The navigate function, when invoked, is a side-effect. The code is calling navigate directly in the body of the component as an unintentional side-effect.
Move the logic into a useEffect hook.
Example:
import React, { useEffect } from "react";
import { generatePath, useParams } from "react-router";
import { useNavigate } from "react-router-dom";
import { usePathPattern } from "./usePathPattern";
export const Authorization = ({ children }) => {
const params = useParams();
const navigate = useNavigate();
const userTherapy = params.therapy;
const name = params.name;
const pattern = usePathPattern();
useEffect(() => {
if (userTherapy === "undefined" && name) {
const pathname = generatePath(pattern, {
name,
therapy: "TEST"
});
navigate(pathname, { replace: true });
}
}, [name, navigate, pattern, userTherapy]);
return children;
};

TypeError: Cannot read properties of undefined (reading 'search')

I am completely new to this. Tried for hours to find some sort of explanation on this.
Basically I am trying to replicate a project to understand the main concepts. In the project the code apparently works just fine, I however receive a "TypeError: Cannot read properties of undefined (reading 'search')" error. I hope that someone here can explain to me, what I am missing.
I believe the Errors to come from the following lines of code:
SigninScreen:
const redirect = props.location.search
? props.location.search.split("=")[1]
: "/";
ProductScreen:
const productId = props.match.params.id;
Kind Regards,
Makani
SigninScreen:
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, } from "react-router-dom";
import { signin } from "../actions/userActions";
import Loadingbox from "../components/LoadingBox";
import MessageBox from "../components/MessageBox";
export default function SigninScreen(props) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const redirect = props.location.search
? props.location.search.split("=")[1]
: "/";
const userSignin = useSelector((state) => state.userSignin);
const { userInfo, loading, error } = userSignin;
const dispatch = useDispatch();
const submitHandler = (e) => {
e.preventDefault();
dispatch(signin(email, password));
};
useEffect(() => {
if (userInfo) {
props.history.push(redirect);
}
}, [props.history, redirect, userInfo]);
return ( ... );
}
ProductScreen:
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, useParams } from "react-router-dom";
import { detailsProduct } from "../actions/productActions";
import LoadingBox from "../components/LoadingBox";
import MessageBox from "../components/MessageBox";
import Rating from "../components/Rating";
export default function ProductScreen(props) {
const productId = props.match.params.id;
const dispatch = useDispatch();
const [qty, setQty] = useState(1);
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect(() => {
dispatch(detailsProduct(productId));
}, [dispatch, productId]);
const addToCartHandler = () => {
props.history.push(`/cart/${productId}?qty=${qty}`);
};
return ( ... );
}
I had same error.
In v6 you have to use useLocaion() like:
const location = useLocation();
const redirect = location.search
? location.search.split('=')[1]
: '/';
From the documentation for React Router v5:
The router will provide you with a location object in a few places:
· Route component as this.props.location
· Route render as ({ location }) => ()
· Route children as ({ location }) => ()
· withRouter as this.props.location
A component receives the location prop automatically in 4 usages mentioned about. Since you have not described withRouter, I can only assume that your case is Option 1.
React Router adds the location prop to the component automatically if it is directly in the Route component.
// if this is the case, SignIn receives a location prop
<Route path="/path" component={SigninScreen} />
If you want to add location prop manually, you can use withRouter higher order component.
export default withRouter(SignInScreen);

history.push is not a function

i am trying to build a login page and when the create account button is clicked in the login /signup page, checking the authentication of the user, it should return to the home page.
But it is showing the error
import React, { useState } from "react";
import "./Login.css";
import { Link, useHistory } from "react-router-dom";
import { auth } from "./firebase";
function Login() {
const history = useHistory;
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const signIn = (e) => {
e.preventDefault();
};
const register = (e) => {
e.preventDefault();
auth
.createUserWithEmailAndPassword(email, password)
.then((auth) => {
console.log(auth);
if (auth) {
history.push("/");
}
})
Just call the useHistory hook like this:
const history = useHistory()
The useHistory hook gives you access to the history instance that you may use to navigate.
How to use:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}

How change url with react-router

I have some component
import { RouteComponentProps, withRouter } from 'react-router';
function MySearchComponent({ match, location, history }: RouteComponentProps) {
const [query, setQuery] = useState<string>('');
useEffect(() => {
console.log('all fine!')
history.replace(`/my_search_page?query=${query}`);
}, [query]);
// some code for change query
}
export const MySearch = withRouter(MySearchComponent);
What's wrong? I'd tried to use history.push
console.log alter right when query changed, but nothing happend
UPD: Sorry. It was my mistake: my application just doesn't support search-parameters
Thanks for your help
In my application I am using useHistory hook
import React, { useEffect } from "react";
import { useHistory } from "react-router-dom";
const Operations = () => {
const history = useHistory();
useEffect(() => {
const res = prepareURLParams(filters);
history.push(getRouterString("/", res));
}, [filters]);
}
export default Operations;

How do I combine useLocation() with useSelector()?

import React from "react"
import { useSelector } from 'react-redux'
import { useLocation } from "react-router"
const BreadCrumb = () => {
const location = useLocation()
const currentPageTitle = useSelector(state => {
// match current location to get the currrent page title from redux store and return it
})
return (
<h2>Home / { currentPageTitle}</h2>
)
}
export default BreadCrumb
This code works fine in the initial render and I do get the intended result { currentPageTitle } but the UI doesn't seem to re-render and stays the same despite route change. Although, if I console.log( location ) before the return statement, it logs successfully on route change. What is the issue here?
I would suggest that you use useEffect hook:
import React, { useEffect, useState } from "react"
import { useSelector } from 'react-redux'
import { useLocation } from "react-router"
const BreadCrumb = () => {
const location = useLocation()
const [currentLocation, setCurrentLocation] = useState('')
const currentPageTitle = useSelector(state => {
console.log(currentLocation);
// Do something with currentLocation
})
useEffect(() => {
if (location) {
setCurrentLocation(location.pathname)
} else {
setCurrentLocation('')
}
}, [location])
return (
<h2>Home / { currentPageTitle}</h2>
)
}
export default BreadCrumb

Resources