I have a simple server that listens on port 8000
and all it does is to return the name of the files inside a directory in this format:
{'Files': ['file1', 'file2', ...]}
I have a React app, that fetches the data using the useEffect
hook and then places the response with the useState
hook.
The problem is that, on the first try it works perfectly, and maybe on the second time as well, but when I refresh for the third time (or more) it just disappears! and I see an error message on the chrome devtools:
Uncaught TypeError: Cannot read properties of undefined (reading 'map')
The React code is:
import './App.css';
import {useEffect, useState} from "react";
function App() {
const [file, setFile] = useState();
useEffect(() => {
async function fetchData() {
const files = await fetch('http://localhost:8000/get_directory?dir=E:\\Learning\\LearningNetworking\\MD')
const file_json = await files.json()
setFile(file_json.File)
}
fetchData()
}, [])
return (
<div className="App">
<header className="App-header">
{file.map(file_name => <p>{file_name}<br/></p>)}
</header>
</div>
);
}
export default App;
I really don't know what's going on, maybe there's a race condition and the react app tries to render the list before fetching it? But doesn't the React useEffect
hook knows when to fetch again and when not?
I tried using the nullish coalescing on this line:
const file_json = await files.json() ?? []
instead of:
const file_json = await files.json()
The server (if needed for debugging reasons) written in fastapi:
from pathlib import Path
from fastapi import FastAPI, Request
from starlette.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(CORSMiddleware,
allow_origins=['*'])
@app.get('/get_directory')
def directory_tree(request: Request):
path = request.query_params.get('dir', None)
return {'Files': [file.name for file in Path(path).iterdir()]}
I'm pretty sure I've got something wrong here in my understanding of React, I am a newbie so I would appreciate your help! Any searches online did not find exactly this problem (maybe it's because I couldn't phrase the problem very well... sorry if it has been asked before!).
CodePudding user response:
The problem is coming from your client code. As you defined your state, initially file
is undefined
. And since fetching data is asynchronous, sometimes the render happens before you get the data. One way to solve this issue is to initiate your state like this:
const [file, setFile] = useState([]);