'REACT - Express : fetching data doesn't work on reload when user connected
I've deploy my first app using React with Nodejs/Express/MongoDB but I'm running through a bug I couldn't find any solution, so I'm coming here to find some help.
This is the app : https://movie-app-marielyse.herokuapp.com/
As soon as the user connects, he can access the data, but if the page is reloaded, the fetch is not working anymore.
Here is the code where the fetch happens :
import './App.css';
import "./index.css"
import React, {useState, useEffect, useRef} from 'react'
import {BrowserRouter as Router, Routes, Route} from 'react-router-dom'
import Register from './components/Register';
import Login from './components/Login'
import Home from './pages/Home';
import Auth from './pages/Auth';
import Movie from './pages/Movie'
import NotFound from './pages/Notfound';
import FavoritesMovies from './pages/Favorites';
import UserContextProvider from './contexts/UserContext';
import RequireAuth from './contexts/RequireAuth';
function App() {
const defaultUser = {name:"Stranger", email: "[email protected]"}
const [moviesList, setMoviesList] = useState([])
const [initialML, setInitialML] = useState([])
const [userInfo, setUserInfo] = useState(defaultUser)
// console.log(userInfo.name)
useEffect( () => {getMovies()}, [])
function getMovies() {
fetch('/movies')
.then(response => response.json())
.then(data => {
const movies= data.movies
setMoviesList(movies)
setInitialML(movies)
})
.catch(err => console.log(err))
}
return (
<div className="App">
<UserContextProvider user={{userInfo, setUserInfo}}>
<Router>
<main>
<Routes>
<Route path="/" element={<Home moviesList={moviesList} setMoviesList={setMoviesList} initialMovieList={initialML}/>}/>
<Route path="/auth/*" element={<Auth />} >
<Route path="login" element={<Login/>} />
<Route path="register" element={<Register/>} />
<Route path="logout" element={<Register/>} />
{/* <Route path="*" element={<NotFound />}/> */}
</Route>
<Route path="movies/:movieId" element={<Movie moviesList={moviesList} setMoviesList={setMoviesList} />} />
<Route path="favorites" element={
<RequireAuth>
<FavoritesMovies />
</RequireAuth>} />
<Route path="*" element={<NotFound />}/>
</Routes>
</main>
</Router>
</UserContextProvider>
</div>
);
}
export default App;
Solution 1:[1]
In general your code can be modified like this, roughy:
- remove fetch /movies from
App
and place it insideHome
- this would make sure useEffect/fetch triggers when/
route is hit. And is good practice to keep things separated and well organized.
App component
function App() {
const defaultUser = {name:"Stranger", email: "[email protected]"}
const [userInfo, setUserInfo] = useState(defaultUser)
return (
<div className="App">
<UserContextProvider user={{userInfo, setUserInfo}}>
<Router>
<main>
<Routes>
<Route exact path="/" element={<Home />}/>
<Route path="/auth/*" element={<Auth />} >
<Route path="login" element={<Login/>} />
<Route path="register" element={<Register/>} />
<Route path="logout" element={<Register/>} />
{/* <Route path="*" element={<NotFound />}/> */}
</Route>
<Route path="movies/:movieId" element={<Movie moviesList={moviesList} setMoviesList={setMoviesList} />} />
<Route path="favorites" element={
<RequireAuth>
<FavoritesMovies />
</RequireAuth>} />
<Route path="*" element={<NotFound />}/>
</Routes>
</main>
</Router>
</UserContextProvider>
</div>
);
}
export default App;
Home component
function Home() {
const [moviesList, setMoviesList] = useState([])
const [initialML, setInitialML] = useState([])
useEffect( () => {getMovies()}, []);
function getMovies() {
fetch('/movies')
.then(response => response.json())
.then(data => {
const movies= data.movies
setMoviesList(movies)
setInitialML(movies)
})
.catch(err => console.log(err))
}
return (....)
}
And i am not sure which version you are using but if it is not v6, more on React.Router could be checked- https://v5.reactrouter.com/web/api/Switch and exact
https://dev.to/danhjoo7/using-a-switch-component-in-react-router-d2k
Solution 2:[2]
<Route path="/" element={<Home moviesList={moviesList} setMoviesList={setMoviesList} initialMovieList={initialML}/>}/>
On this line or where ever there is moviesList
and initialML
try doing:
<Route path="/" element={<Home moviesList={moviesList && moviesList} setMoviesList={setMoviesList} initialMovieList={initialML && initialML}/>}/>
Your fetch request is async so it takes some time but the compenent is already rendered before that thats probably it looks data is not being fetched.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | RBT |