React _this3.deleteArticle不是一个函数

时间:2019-02-12 21:05:49

标签: javascript reactjs

在查看了其他一些类似的帖子之后,我仍然不确定为什么会收到以下错误:

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);
      } 
    })  
  }
}

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)
            }))
        })
}