This is my first time using react-router-dom and state is causing me issues, it is being returned to me as null. I have seen that there are answers here already but they do not solve my problem as I am using the provided answers as exactly as I can.
I am attempting to have a state object: {token: boolean, setToken: function}
initialized in App.js
to be sent down to ProfilePage.js
(in this case specifically but later to all page components). However, in ProfilePage.js
, state is null. I have also tried sending the string {'hello'}
and a simple boolean {data: true}
with no change to state
My full App.js
code:
import { useState } from "react";
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import SearchPage from './pages/Search.page';
import HomePage from './pages/Home.page';
import ProfilePage from './pages/Profile.page';
import AddEntryPage from './pages/AddEntry.page';
import LoginPage from "./pages/Login.page";
import CreateUserPage from "./pages/CreateUser.page";
import './App.css';
function App() {
const [token, setToken] = useState(false);
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to='/profile' state={{token, setToken}}>Profile</Link>
</li>
<li className='right-edge-pusher'>
<Link to='/' state={{token, setToken}}>Home</Link>
</li>
<li>
<Link to='/add' state={{token, setToken}}>Add</Link>
</li>
<li>
<Link to='/search' state={{token, setToken}}>Search</Link>
</li>
</ul>
</nav>
<Routes>
<Route path='/' element={<HomePage /> }/>
<Route path='/profile' element={<ProfilePage />}/>
<Route path='/add' element={<AddEntryPage />}/>
<Route path='/search' element={<SearchPage />}/>
<Route path="/login" element={<LoginPage /> }/>
<Route path="/user" element={<CreateUserPage /> }/>
</Routes>
</div>
</Router>
);
}
export default App;
My full ProfilePage.js
code:
import { useState } from "react";
import { useQuery } from "react-query";
import { Link, useLocation } from 'react-router-dom';
import axios from 'axios';
import PostSnippet from '../components/PostSnippet';
function ProfilePage() {
const { state } = useLocation();
console.log(state);
const [enabled, setEnabled] = useState(false);
const fetchProfile = () => {
return axios.get("http://localhost:5000/saved")
}
const { data, isError, error, isLoading } = useQuery('profile', fetchProfile, { enabled });
return (
<div>
{ true /*note: will later be changed to !token*/ &&
<>
<Link to={'/login'} /*state to be passed here as well*/ >Login</Link>
<br/>
<br/>
<Link to={'/user'} /*state to be passed here as well*/ >Create User</Link>
</>
}
{ isLoading && <h2>Loading...</h2> }
{ isError && <h2>{error.response.data.message.message}</h2> }
{ data &&
data.data.map(item => {
return (
<PostSnippet
key={item.id}
plantName={item.name}
plantTempRange={`${item.sow_temp_range}f`}
plantZone={item.planting_zone}
plantSunReq={`${item.sun_req} sun`}
plantDescription='To be added...'
/>
);
})
}
</div>
);
}
export default ProfilePage;
Thank you!
2
Answers
The state you have passed to the profile page can be accessed using the code provided below:
I hope this answer helps you resolve your scenario.
The values passed in route/link state must be JSON serializable. You can’t pass functions, e.g. the
setToken
, through the state, it will nullify the entire state object.My suggestion here would be to use a React Context to pass down the
token
andsetToken
callback. TheOutlet
component is an easy and trivial way to provide this context value, and the routed components that care to read/access the value will use theuseOutletContext
hook.Example:
Any component rendered within the layout route’s provided outlet context can access the value as
const { token, setToken } = useOutletContext();
.