So, I've been struggling with this and couldn't really find a solution. I have a Flask backend that does some operations and returns a JSON response like so
server.py
from flask import Flask
from pyresparser import ResumeParser
app = Flask(__name__)
# Details API Route
@app.route("/details")
def details():
resume_data = ResumeParser(r'D:\React\Candetect\backend\Uploaded_Resumes\OmkarResume.pdf').get_extracted_data()
email = resume_data.get('email')
return {"Information":[email]}
if __name__== "__main__":
app.run(debug=True)
Now, I'm getting this JSON response in App.jsx like so
const [data, setData] = useState([])
useEffect(() =>{
fetch("/details").then(
res => res.json()
).then(
data => {
setData([data.Information])
console.log(data)
}
)
}, [])
And I'm trying to display it like so
<div>
{(data.length === 0) ? (
<p>Loading...</p>
) : (
data.members.map((member, i) => (
<h3 key={i}>{member.email}</h3>
))
)}
</div>
</div>
The problem, the page loads up, I get loading... message displayed, then as the data is fetched I get this error TypeError: Cannot read properties of undefined (reading 'map')
For some reason it's considering it to be undefined.
This is what I get when I console.log(data)
{
"Information": [
"[email protected]"
]
}
CodePudding user response:
Effects let you run some code after rendering so that you can synchronize your component with some system outside of React
So basically, when your code will run for the first time, the code inside useEffect won't run. Using something like this, you can have a fallback render until your data loads.
if (!data) {
return <p>Loading...</p>;
}
A better solution would be to have a loading state that keeps track of the data that is being loaded.
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("/details")
.then((res) => res.json())
.then((data) => {
setData([data.Information]);
setLoading(false);
console.log(data);
});
}, []);
if (loading && !data) {
return <p>Loading...</p>;
}
if (!loading && !data) {
return <p>Opps. Something`s wrong</p>;
}
return (
<div>
{data.members.map((member, i) => (
<h3 key={i}>{member.email}</h3>
))}
</div>
);
React v18 Fix
If you have the problem of useEffect firing twice, you can use something like to prevent it from doing that.
function App() {
const effectRan = useRef(false);
useEffect(() => {
if (effectRan.current === true || process.env.NODE_ENV !== "development") {
//
//Code that should only run once !
//
}
return () => (effectRan.current = true);
}, []);
return <p></p>;
}
export default App;
CodePudding user response:
So I ended up switching my code a bit. Here's what I did instead:
App.jsx
const [initialData, setInitialData] = useState([{}])
useEffect(() => {
fetch('/details').then(
response => response.json()
).then(data => setInitialData(data))
}, []);
return (
<div>
<h3>Hello {initialData.name}</h3>
</div>
</div>
);
Then, in server.py
from flask import Flask
app = Flask(__name__)
# Details API Route
@app.route("/details")
def details():
data = func(r'path\to\pdf').get_data()
return {"email":data.get('email'),
"mobile_number":data.get('mobile_number'),
"name":data.get('name'),
}
if __name__== "__main__":
app.run(debug=True)