在查看了其他一些类似的帖子之后,我仍然不确定为什么会收到以下错误:
TypeError: _this3.deleteArticle is not a function
根据我的收集,问题是deleteArticle
中没有包含state
。但是,我认为.bind(this)
应该将其绑定到state
从而解决此问题。为什么这不起作用,我该怎么做才能纠正它?
正在通过以下方法在render方法中调用deleteArticle
函数:
<td onClick={() => this.deleteArticle(article.Id).bind(this) }>
<Glyphicon glyph='trash' />
</td>
如下所示:
deleteArticle(id) {
fetch('https://localhost:44360/api/articles/' + id, {
method: 'DELETE'
}).then((response) => response.json())
.then((responseJson) => {
var deletedId = responseJson.id;
var index = this.state.articles.findIndex(function(o){
return o.id === deletedId;
})
if (index !== -1){
this.state.articles.splice(index, 1);
}
})
}
为了完整起见,还有完整的组件:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Glyphicon } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';
export class ArticlesIndex extends Component {
displayName = ArticlesIndex.name
constructor(props) {
super(props);
this.state = { articles: [], loading: true };
fetch('https://localhost:44360/api/Articles/')
.then(response => response.json())
.then(data => {
this.setState({ articles: data, loading: false });
});
}
static renderArticlesTable(articles) {
return (
<table className='table'>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{articles.map(article =>
<tr key={article.id}>
<td>{article.id}</td>
<td>{article.title}</td>
<td dangerouslySetInnerHTML={{ __html: article.description }}></td>
<td>
<LinkContainer to={'/articles/edit/' + article.id}>
<Glyphicon glyph='edit' />
</LinkContainer>
</td>
<td onClick={() => this.deleteArticle(article.Id).bind(this) }>
<Glyphicon glyph='trash' />
</td>
</tr>
)}
</tbody>
</table>
);
}
render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: ArticlesIndex.renderArticlesTable(this.state.articles);
return (
<div>
<h1>Articles</h1>
{contents}
</div>
);
}
deleteArticle(id) {
fetch('https://localhost:44360/api/articles/' + id, {
method: 'DELETE'
}).then((response) => response.json())
.then((responseJson) => {
var deletedId = responseJson.id;
var index = this.state.articles.findIndex(function(o){
return o.id === deletedId;
})
if (index !== -1){
this.state.articles.splice(index, 1);
}
})
}
}
答案 0 :(得分:3)
static
方法未绑定到类的实例,并且具有与典型组件不同的上下文。
其结果是,类中的其他函数/变量将无法通过this
关键字访问,因为它们的上下文不同。
更改函数声明:
static renderArticlesTable(articles)
以下:
renderArticlesTable = articles =>
可以解决您的问题,因为我看不到您的函数是静态的任何原因。另外,使其成为箭头函数会自动将其绑定到类的上下文。
您的通话:
ArticlesIndex.renderArticlesTable(this.state.articles)
现在将是:
this.renderArticlesTable(this.state.articles)
我还建议您将deleteArticle
函数更改为不需要绑定的箭头函数:
deleteArticle = id => {
此外,请勿在您的构造函数中设置诺言来触发setState
。如果您的fetch
请求发送数据太早,则将设置已卸载组件的状态。提取数据时使用componentDidMount
:
constructor(props) {
super(props);
this.state = { articles: [], loading: true };
}
componentDidMount(){
fetch('https://localhost:44360/api/Articles/')
.then(response => response.json())
.then(data => {
this.setState({ articles: data, loading: false });
});
}
在我这样做的同时,您也可以将三元条件直接放入JSX中:
render() {
const { loading, articles } = this.state
return (
<div>
<h1>Articles</h1>
{loading ?
<p><em>Loading...</em></p>
:
this.renderArticlesTable(articles)
}
</div>
);
}
我还注意到您正在尝试直接在deleteArticle
函数中修改状态。您必须先使用setState
才能修改状态。
要删除具有特定值的项目,可以使用filter
从先前状态中取出具有相应id
的项目:
deleteArticle = id => {
fetch('https://localhost:44360/api/articles/' + id, {
method: 'DELETE'
}).then(response => response.json())
.then(({ id }) => { //Deconstructs you responseJson
this.sestState(prev => ({
articles: prev.articles.filter(article => article.id !== id)
}))
})
}