首页 > 解决方案 > React _this3.deleteArticle 不是一个函数

问题描述

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

TypeError: _this3.deleteArticle is not a function

据我所知,问题是deleteArticle不包含在state. 但是,我认为.bind(this)应该将其绑定到state从而解决此问题。为什么这不起作用,我该怎么做才能纠正它?

deleteArticle函数在 render 方法中通过以下方式调用:

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

标签: javascriptreactjs

解决方案


方法static不绑定到类的实例,并且将具有与典型组件不同的上下文。

这样做的结果是您的类中的其他函数/变量将无法通过this关键字访问,因为它们的上下文不同。

更改您的函数声明:

static renderArticlesTable(articles)

到以下:

renderArticlesTable = articles => 

可以解决您的问题,因为我认为您的函数没有任何理由是静态的。此外,使其成为箭头函数将自动将其绑定到您的类的上下文。

您的电话:

 ArticlesIndex.renderArticlesTable(this.state.articles)

现在将是:

this.renderArticlesTable(this.state.articles)

我还建议将您的deleteArticle函数更改为不需要绑定的箭头函数:

deleteArticle = id => {

此外,不要setState在构造函数中设置触发 a 的承诺。如果您的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)
            }))
        })
}

推荐阅读