I am using an useEffect inside a Context. I think the useEffect should run after load the page, but it does not work, but if I refresh the page(F5) then it works.
I am new Using React, but I think it should work with the empty array as arg.
This is the Context:
import { createContext, useState, useEffect } from "react";
const PatientContext = createContext();
export const PatientsProvider = (props) => {
const {children} = props;
const [patients, setPatients] = useState([]);
//get the patients from the database
useEffect( () => {
const url = `${import.meta.env.VITE_BACKEND_URL}/api/patients`;
const token = localStorage.getItem("token");
if(!token) return;
const getPatients = async () => {
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
"Authorization" : `Bearer ${token}`
}
});
const result = await response.json();
if (!response.ok){
throw new Error(result.msg);
}
const {createdAt, __v, updatedAt, ...savedPatient} = result;
setPatients(result)
setLoading(false);
} catch (error) {
setLoading(false)
setAlert({msg: error.message, error1: true})
console.log(error)
}
}
getPatients();
}, [])
EDIT:
Now I realized that the problem is the useEffect render the first time in the login page (before I need it, because I need it after the login page), this is happening because PatientProvider is parent of all the components even Login component, but now I do not know how to set this provider to only "after login components".
Here is my Routes:
function App() {
return (
<BrowserRouter>
<AuthProvider>
<PatientsProvider>
<Routes>
<Route path="/" element={< Authlayout />}>
<Route index element={ <Login /> } />
<Route path="sign-up" element= {<SignUp />}/>
<Route path="forgot-password" element= {<ForgotPassword />}/>
<Route path="forgot-password/:token" element= {<ResetPassword />}/>
<Route path="confirm-account/:token" element= {<Confirm />}/>
</Route>
<Route path="/admin" element={<LoginLayout />}>
<Route index element={<AdminPatients />} />
<Route path="profile" element= {<Profile />}/>
<Route path="change-password" element= {<ChangePass />}/>
</Route>
</Routes>
</PatientsProvider>
</AuthProvider>
</BrowserRouter>
)
}
It seems like your token is not set by the time the component mounts and calls this useEffect().
I can think of 2 options:
token
as a dependency in useEffect():// assuming token is stored in context state
// and will update
const {token} = useAuthContext()
useEffect(() => {
// ...
// will be called every time the token changes
}, [token])
import { useLocalStorageValue } from '@react-hookz/web'
const PatientsProvider = (props) => {
const [token] = useLocalStorageValue('token')
useEffect(() => {
// do sth with the token
}, [token])