Reputation: 71
My code is malfunctioning and showing TypeError: userData is undefined error. I am taking data from MongoDB to show on the website. {userData.name} is creating the trouble. set user data part of UseState is working fine and am getting the data in the console from MongoDB. The error seems to be in the frontend part.
Code:-
import PropTypes from "prop-types";
import React, { Fragment, useEffect, useState } from "react";
import MetaTags from "react-meta-tags";
import { BreadcrumbsItem } from "react-breadcrumbs-dynamic";
import Card from "react-bootstrap/Card";
import Accordion from "react-bootstrap/Accordion";
import LayoutOne from "../../layouts/LayoutOne";
import Breadcrumb from "../../wrappers/breadcrumb/Breadcrumb";
import { useHistory } from "react-router-dom";
const MyAccount = ({ location }) => {
const { pathname } = location;
const history = useHistory();
const [userData, setUserData] = useState();
const callAccount = async () => {
try {
const res = await fetch('/myaccount', {
method: 'GET',
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
credentials: "include"
});
const data = await res.json();
console.log(data);
setUserData(data);
if (!res.status === 200)
{
const error = new Error(res.error);
throw error;
}
} catch (err) {
console.log(err);
history.push('/login')
}
}
useEffect(() => {
callAccount();
}, []);
return (
<Fragment>
<MetaTags>
<title>Flone | My Account</title>
<meta
name="description"
content="Compare page of flone react minimalist eCommerce template."
/>
</MetaTags>
<BreadcrumbsItem to={process.env.PUBLIC_URL + "/"}>Home</BreadcrumbsItem>
<BreadcrumbsItem to={process.env.PUBLIC_URL + pathname}>
My Account
</BreadcrumbsItem>
<LayoutOne headerTop="visible">
{/* breadcrumb */}
<Breadcrumb />
<div className="myaccount-area pb-80 pt-100">
<div className="container">
<div className="row">
<div className="ml-auto mr-auto col-lg-9">
<div className="myaccount-wrapper">
<form method="GET">
<Accordion defaultActiveKey="0">
<Card className="single-my-account mb-20">
<Card.Header className="panel-heading">
<Accordion.Toggle variant="link" eventKey="0">
<h3 className="panel-title">
<span>1 .</span> My account information{" "}
</h3>
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>
<div className="myaccount-info-wrapper">
<div className="account-info-wrapper">
<h5>Your Personal Details { userData.name}</h5>
</div>
<div className="row">
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>First Name </label>
<input type="text" />
</div>
</div>
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>Last Name</label>
<input type="text" />
</div>
</div>
<div className="col-lg-12 col-md-12">
<div className="billing-info">
<label>Email Address</label>
<input type="email" />
</div>
</div>
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>Telephone</label>
<input type="text" />
</div>
</div>
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>Fax</label>
<input type="text" />
</div>
</div>
</div>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
<Card className="single-my-account mb-20">
<Card.Header className="panel-heading">
<Accordion.Toggle variant="link" eventKey="1">
<h3 className="panel-title">
<span>2 .</span> Change your password
</h3>
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>
<div className="myaccount-info-wrapper">
<div className="account-info-wrapper">
<h4>Change Password</h4>
<h5>Your Password</h5>
</div>
<div className="row">
<div className="col-lg-12 col-md-12">
<div className="billing-info">
<label>Password</label>
<input type="password" />
</div>
</div>
<div className="col-lg-12 col-md-12">
<div className="billing-info">
<label>Password Confirm</label>
<input type="password" />
</div>
</div>
</div>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
<Card className="single-my-account mb-20">
<Card.Header className="panel-heading">
<Accordion.Toggle variant="link" eventKey="2">
<h3 className="panel-title">
<span>3 .</span> Modify your address book entries{" "}
</h3>
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="2">
<Card.Body>
<div className="myaccount-info-wrapper">
<div className="account-info-wrapper">
<h4>Address Book Entries</h4>
</div>
<div className="entries-wrapper">
<div className="row">
<div className="col-lg-12 col-md-12 d-flex align-items-center justify-content-center">
<div className="entries-info text-center">
<p>John Doe</p>
<p>Paul Park </p>
<p>Lorem ipsum dolor set amet</p>
<p>NYC</p>
<p>New York</p>
</div>
</div>
</div>
</div>
<div className="billing-back-btn">
<div className="billing-btn">
<button type="submit">Continue</button>
</div>
</div>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</form>
</div>
</div>
</div>
</div>
</div>
</LayoutOne>
</Fragment>
);
};
MyAccount.propTypes = {
location: PropTypes.object
};
export default MyAccount;
Upvotes: 0
Views: 836
Reputation: 943967
const [userData, serUserData] = useState();
The initial value is the argument you pass to useState
.
You haven't passed any value, so it is initially undefined
.
At some point in the future the Ajax request will come back and you might call setUserData
to assign a different value, but by then you've tried to read userData.name
and thrown an exception.
You need to account for that in your code. A typical approach would be to do something like:
if (!userData) {
return <ALoadingComponent />
}
return /* what you have now */
Upvotes: 2
Reputation: 12787
Because the initial of userData
is undefined
. Just update it with an object
const [userData, setUserData] = useState({});
Upvotes: 2