Reputation: 582
I've checked out several similar questions and tried to implement their answers, but still no luck. Here's the code:
import React, {Component, Fragment} from "react";
import Files from "./client/files";
import axios from "axios";
const styles = {
card: {
border: "1px solid transparent",
borderRadius: "8px",
padding: "20px",
boxShadow: "0 1px 2px 0 rgba(60,64,67,0.302), 0 2px 6px 2px rgba(60,64,67,0.149)",
maxWidth: "75%"
},
h1: {
marginTop: "30px"
},
link: {
color: '#000'
},
i: {
fontSize: '24px',
margin: '0 20px'
},
h4: {
color: "#24486f",
letterSpacing: "1.2px"
},
h5: {
color: "#24486f",
letterSpacing: "1.2px"
}
}
class Client extends Component {
constructor() {
super();
this.state = {
client_files: [],
user_id: "",
client_name: "",
version_ref: "",
first_name: "",
last_name: "",
email: "",
phone: "",
website: "",
file_refs: []
};
this.getFileData = this.getFileData.bind(this);
}
componentDidMount() {
console.log(this.props.currentUser)
this.getFileData();
}
getFileData() {
let fileRefs = this.props.currentUser.file_refs;
let fileData = [];
for (let i = 0; i < fileRefs.length; i++) {
axios.get("/api/file/get-file/" + fileRefs[i])
.then( res => {
console.log(res.data.response)
fileData.push(res.data.response);
this.setState({
client_files: fileData
})
})
.catch( err => console.log(err.response.data))
}
}
render() {
return(
<Fragment>
<div className="container">
<div className="row">
<div className="col-lg-12">
<h1 style={styles.h1}> PartnerPortal </h1>
<hr/>
<h4 style={styles.h4}>
<em>Welcome, {this.props.currentUser.first_name} {this.props.currentUser.last_name}</em>
</h4>
<h5 style={styles.h5}>
<em>{ this.props.currentUser.client_name}</em>
</h5>
<hr/>
<p> PartnerPortal allows you quick access to files, resources, and other documents that are part of your current contract with .... Company</p>
<div style={styles.card}>
<table className="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Type</th>
<th scope="col">File Name</th>
</tr>
</thead>
<tbody>
{this.state.client_files.map(( file, i ) => (
<tr key={i}>
<td>{i}</td>
<td style={styles.p}>
{ file.file_type === "PDF" &&
<a href={file.file_url}><span style={styles.link}><i style={styles.i} className="far fa-file-pdf"></i></span></a>
}
{ file.file_type === "DOC" &&
<a href={file.file_url}><span style={styles.link}><i style={styles.i} className="far fa-file-alt"></i></span></a>
}
{ file.file_type === "Directory" &&
<a href={file.file_url}><span style={styles.link}><i style={styles.i} className="far fa-folder"></i></span></a>
}
{ file.file_type === "Presentation" &&
<a href={file.file_url}><span style={styles.link}><i style={styles.i} className="far fa-file-powerpoint"></i></span></a>
}
</td>
<td>{file.file_name}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</Fragment>
);
}
}
export default Client;
The currentUser is passed down as props from the parent component, and contains an array of file references (this.props.currentUser.file_refs). The console.log
inside componentDidMount()
accurately logs all the file references to the console. However, when the getFileData()
function runs, it returns the error: TypeError: Cannot read property 'length' of undefined
.
What I've already tried:
- changing to componentWillMount()
- adding if (this.props.currentUser){this.getFileData())
in my componentDidMount()
function
- adding if (!this.props.currentUser.file_refs) { return null ) return ( <Fragment> ..... </Fragment>
Anybody know what I'm doing wrong here?
Edit: Adding routes from parent component, Main.js
{ (isLoggedIn && currentUser.isAdmin) &&
<Route exact path="/" render={() => (<IodDash currentUser={this.props.currentUser}/>)}/>
}
{ (isLoggedIn && !currentUser.isAdmin) &&
<Route exact path="/" render={() => (<ClientDash currentUser={this.props.currentUser}/>)}/>
}
Upvotes: 1
Views: 49
Reputation: 64
It looks like this.props.currentUser.file_refs
isn't fully loaded before setting it to the fileRefs
variable in your function getFileData()
and that is why you are getting the error TypeError: Cannot read property 'length' of undefined
. You might want to write a check in the parent component that makes sure the data is loaded before passing the prop to the child.
Upvotes: 1