Reputation: 312
Im trying to figure out why is it that when I use useNavigate
with my first component the state
appears null
when I render my second component?
I've checked the answers found here but did not find any luck :Cannot pass state using useNavigate() in react router dom v6
Here's my code from first component:
export default SignInPage(){
const loginEmailRef = useRef('');
const loginPassWordRef = useRef('');
const navigate = useNavigate();
return(
<Box className='sign-in-textfield-box' display='flex' flexDirection='column' alignItems='center'>
<TextField variant='standard' label='email' sx={{ mb: 2, width: '30vw' }} inputRef={loginEmailRef} />
<TextField variant='standard' label='password' type='password' sx={{ width: '30vw' }} inputRef={loginPassWordRef} />
<Button
sx={{ mt: 5, fontSize: '17px', }}
onClick={async (event) => {
event.preventDefault();
try {
const response = await signInUser(loginEmailRef.current.value, loginPassWordRef.current.value);
if (response !== 'error') {
console.log('response: ', response);
********************************
// response does exist as an object with {name: ..., email:... etc}, but when i pass the response with navigate it says null on my other page
navigate('/HomePage', {state: {response}});
********************************
// <Link to={'/HomePage'} state={{state: response} }/>
} else {
alert('Error signing in: ', response);
}
// history('/HomePage');
} catch (error) {
console.log('error puhsing to page: ', error);
}
}}>SignIn</Button>
</Box>
);
}
Here's the code on my other page:
export default HomePage(props) {
const {state} = useLocation();
useEffect( ()=> {
// here consolo.log says state: null
console.log(
'state: ', state
);
}, [])
return(
<Box> Something here </Box>
);
}
EDIT:
Response from response
Object {
providerId: "firebase",
proactiveRefresh: {…},
reloadUserInfo: {…},
reloadListener: null,
uid: "some-user-id-here",
auth: {…},
stsTokenManager: {…},
accessToken: 'some-token-here',
displayName: null,
email: "[email protected]", …
}
The initial page is SignInPage()
then once the user successfully signed it he/she will be redirected to HomePage()
My App.js:
import { Route, Routes } from 'react-router-dom';
import HomePage from './components/Pages/HomePage/HomePage';
import SignInAndUpPage from './components/Pages/SignInAndUp/SignInAndUpPage';
function App() {
return (
<div>
<Routes>
<Route path='/' element={<SignInAndUpPage />} />
<Route path='/HomePage' element={<HomePage />} />
</Routes>
</div>
);
}
export default App;
EDIT # 2: signInUser
method:
export async function signInUser(email, password) {
try {
const response = await signInWithEmailAndPassword(auth, email, password);
console.log('sign in successful. UID: ', response.user.uid);
const uid = await loadUserData(response.user.uid)
return response.user;
} catch (error) {
console.log('error signin use: ', error.message);
return 'error';
}
}
Upvotes: 2
Views: 5653
Reputation: 202618
Values sent in route state should be serializable. Perhaps one of these {...}
response object values contains a non-serializable object, like a function.
Response from response
Object { providerId: "firebase", proactiveRefresh: {…}, // <-- serializable? reloadUserInfo: {…}, // <-- serializable? reloadListener: null, uid: "some-user-id-here", auth: {…}, stsTokenManager: {…}, // <-- serializable? accessToken: 'some-token-here', displayName: null, email: "[email protected]", … }
For example, functions are typically named using a verb, as in, the function is doing some action. The reloadUserInfo
sounds like it invokes an action.
Instead of blindly passing the entire response object in route state, select only the properties necessary for the receiving route.
Example:
const response = await signInUser(
loginEmailRef.current.value,
loginPassWordRef.current.value
);
if (response !== 'error') {
console.log({ response });
// response does exist as an object with {name: ..., email:... etc}
const { accessToken, email, name, uid } = response;
const state = { accessToken, email, name, uid };
navigate('/HomePage', { state });
} ...
Upvotes: 3