当我映射 this.state 中的填充数组时,为什么它 return 未定义?
When I map over a populated array in this.state, why does it return undefined?
在我的应用程序中,我有一个在用户登录后呈现的主页组件。在这个主组件的 componentDidMount 中,我获取了与登录用户关联的文档。 fetch 调用有效,响应中填充了正确的数据。我获取此数据并进行 this.setState 调用,将获取的数据设置为 this.state.
在主组件渲染函数中,我插入了 JSX,它调用一个函数来映射 this.state.docs 并显示该数据。即使 this.state 中的数据可以成功记录到 Home 组件的渲染函数中,但数据映射的结果始终 returns undefined.
如果我创建一个新文档,它确实会被插入并正确显示,但旧文档永远不会显示。
这是我的主页组件:
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;
您正在将状态中的 docs
设置为 [resp.data.docs]
,这是数组中的数组。直接使用resp.data.docs
数组代替:
this.setState({
docs: resp.data.docs,
username: resp.data.username,
userid: resp.data.userid,
loading: false
});
在我的应用程序中,我有一个在用户登录后呈现的主页组件。在这个主组件的 componentDidMount 中,我获取了与登录用户关联的文档。 fetch 调用有效,响应中填充了正确的数据。我获取此数据并进行 this.setState 调用,将获取的数据设置为 this.state.
在主组件渲染函数中,我插入了 JSX,它调用一个函数来映射 this.state.docs 并显示该数据。即使 this.state 中的数据可以成功记录到 Home 组件的渲染函数中,但数据映射的结果始终 returns undefined.
如果我创建一个新文档,它确实会被插入并正确显示,但旧文档永远不会显示。
这是我的主页组件:
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;
您正在将状态中的 docs
设置为 [resp.data.docs]
,这是数组中的数组。直接使用resp.data.docs
数组代替:
this.setState({
docs: resp.data.docs,
username: resp.data.username,
userid: resp.data.userid,
loading: false
});