In my app I have a home component that is rendered after a user logins. In this home component's componentDidMount I fetch the documents associated with the logged in user. The fetch call works and the response is populated with the correct data. I take this data and make a this.setState call, setting the fetched data to this.state.
In the home components render function I insert JSX that calls a function to map over this.state.docs and display that data. Even though the data in this.state can be logged successfully in the Home component's render function, the result of mapping over the data always returns undefined.
If i create a new document it does get inserted and displays correctly, but the older documents never display.
Here's my home component:
import React from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
const axiosConfig = {
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
};
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
docs: [],
username: '',
userid: '',
newDocumentName: '',
newDocumentPassword: '',
loading: true
};
console.log('this.props in home constructor ', this.props);
}
newDoc() {
console.log('this.state before new doc ', this.state);
axios(localStorage.getItem('url') + '/newDoc', {
method: 'post',
data: {
title: this.state.newDocumentName,
password: this.state.newDocumentPassword
},
withCredentials: true
}).then(resp => {
console.log('the response to new doc ', resp);
this.setState({
docs: [...this.state.docs, resp.data.document],
newDocumentName: '',
newDocumentPassword: ''
});
});
}
renderDocumentList() {
return this.state.docs.map((doc, i) => (
<div key={i}>
<Link to={`/editDocument/${doc._id}`}>{doc.title}</Link>
</div>
));
}
logout() {
axios
.post('http://localhost:3000/logout')
.then(resp => {
this.props.history.replace('/');
})
.catch(error => console.log(error));
}
async componentDidMount() {
try {
let resp = await axios
.get(
localStorage.getItem('url') +
'/getAllDocs/' +
this.props.match.params.userid,
axiosConfig
)
.then(resp => {
console.log('awaited response in comp did mount of home ', resp);
this.setState({
docs: [resp.data.docs],
username: resp.data.username,
userid: resp.data.userid,
loading: false
});
});
} catch (e) {
console.log(e);
}
}
render() {
if (this.state.loading) {
return (
<div>
<h2>Loading...</h2>
</div>
);
} else {
return (
<div className="page-container">
<div className="document-header">
<button className="logout-button" onClick={() => this.logout()}>
Logout
</button>
<h3>Welcome, {this.state.username}.</h3>
</div>
<div className="create-or-share-document-div">
<input
type="text"
placeholder="New document name"
name="newDocumentName"
value={this.state.newDocumentName || ''}
onChange={event => {
this.setState({ newDocumentName: event.target.value });
}}
style={{ width: '30%' }}
/>
<input
type="password"
placeholder="new document password"
name="newDocumentPassword"
value={this.state.newDocumentPassword || ''}
onChange={event => {
this.setState({ newDocumentPassword: event.target.value });
}}
style={{ width: '30%' }}
/>
<button
style={{
border: 'solid black 1px',
padding: '5px',
borderRadius: '10px',
height: '3%',
backgroundColor: 'lightgrey'
}}
onClick={() => this.newDoc()}
>
Create Document
</button>
</div>
<div className="document-container">
<div className="document-list">
<p>My Documents:</p>
<ul>{this.renderDocumentList()}</ul>
</div>
</div>
<br />
<div className="create-or-share-document-div">
<input
style={{ width: '30%' }}
type="text"
placeholder="paste a docID to collab on a doc"
ref="sharedDoc"
/>
<button
style={{
border: 'solid black 1px',
padding: '5px',
borderRadius: '10px',
height: '3%',
backgroundColor: 'lightgrey'
}}
>
Add Shared Doc
</button>
</div>
</div>
);
}
}
}
export default Home;
You are setting the docs
in state to [resp.data.docs]
, which is an array inside of an array. Use the resp.data.docs
array directly instead:
this.setState({
docs: resp.data.docs,
username: resp.data.username,
userid: resp.data.userid,
loading: false
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.