首页 > 解决方案 > 收到“this.setState 不是函数”错误

问题描述

我正在为我的基本待办事项列表应用程序创建一个删除功能;但是,当我尝试从列表中删除某个项目并再次设置状态时遇到了问题。它一直给我一个this.setState is not a function错误。问题在deleteTodo(id).

我的 TodoStore.js

import { EventEmitter } from "events";

import dispatcher from "../dispatcher";
import * as TodoActions from "../actions/TodoActions";

class TodoStore extends EventEmitter {
  constructor() {
    super()
    this.deleteTodo = this.deleteTodo.bind(this)
    this.state = { todos: [
      {
        id: 113464613,
        text: "Go Shopping"
      },
      {
        id: 235684679,
        text: "Pay Water Bill"
      },
    ]};
  }

  createTodo(text) {
    const id = Date.now();

    this.state.todos.push({
      id,
      text,
    });

    this.emit("change");
  }

  deleteTodo(id) {
    const todos = this.state.todos.filter(todo => id !== todo.id)
    console.log(todos)
    this.setState({
      todos: todos
    })
    this.emit("change")
  }

  getAll() {
    return this.state.todos;
  }

  handleActions(action) {
    switch(action.type) {
      case "CREATE_TODO": {
        this.createTodo(action.text);
        break;
      }
      case "DELETE_TODO": {
        this.deleteTodo(action.id);
        break;
      }
    }
  }

}

const todoStore = new TodoStore;
dispatcher.register(todoStore.handleActions.bind(todoStore));
window.dispatcher = dispatcher
export default todoStore;

控制台中的错误消息:

TodoStore.js:46 Uncaught TypeError: _this.setState is not a function
    at TodoStore._this.deleteTodo (TodoStore.js:46)
    at TodoStore._this.handleActions (TodoStore.js:63)
    at Dispatcher._invokeCallback (Dispatcher.js:198)
    at Dispatcher.dispatch (Dispatcher.js:174)
    at Object.deleteTodo [as b] (TodoActions.js:11)
    at Todos.deleteTodo (Todos.js:34)
    at onClick (Todos.js:51)
    at HTMLUnknownElement.callCallback (react-dom.development.js:145)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:195)
    at invokeGuardedCallback (react-dom.development.js:248)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:262)
    at executeDispatch (react-dom.development.js:593)
    at executeDispatchesInOrder (react-dom.development.js:615)
    at executeDispatchesAndRelease (react-dom.development.js:713)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:724)
    at forEachAccumulated (react-dom.development.js:694)
    at runEventsInBatch (react-dom.development.js:855)
    at runExtractedEventsInBatch (react-dom.development.js:864)
    at handleTopLevel (react-dom.development.js:4857)
    at batchedUpdates$1 (react-dom.development.js:17498)
    at batchedUpdates (react-dom.development.js:2189)
    at dispatchEvent (react-dom.development.js:4936)
    at interactiveUpdates$1 (react-dom.development.js:17553)
    at interactiveUpdates (react-dom.development.js:2208)
    at dispatchInteractiveEvent (react-dom.development.js:4913)

标签: javascriptreactjsflux

解决方案


首先,我将这个类声明为一个 React 组件,没有它你将无法拥有“状态”,也无法访问 setState 函数(它是创建新状态的函数)。

然后我不会绑定函数,只是在你想在类中声明的每个函数中,我会按照我在代码中指出的以下方式进行绑定:

nameOfFunction = () =>

使用这种形式(箭头函数),您可以获得范围,因此能够使用它来访问状态。

最后,当你推动添加一个新元素时,这在 React 中是被禁止的。状态是不可变的,您只能创建一个新状态来进行任何更改,因此我们使用 setState 并通过 ...this.state.todos(传播运算符)帮助自己。

它通过创建一个新数组并添加您需要的带有 id 和文本的对象来做到这一点。

我希望我对你有所帮助。最好的,

class TodoStore extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          todos: [
            {
              id: 113464613,
              text: "Go Shopping",
            },
            {
              id: 235684679,
              text: "Pay Water Bill",
            },
          ],
        };
      }

      createTodo = text => {
        const id = Date.now();

        this.setState({
          todos: [...this.state.todos, { id, text }],
        });

        this.emit("change");
      };

      deleteTodo = id => {
        const todos = this.state.todos.filter(todo => id !== todo.id);
        console.log(todos);

        this.setState({
          todos,
        });

        this.emit("change");
      };

      getAll = () => this.state.todos;

      handleActions = action => {
        switch (action.type) {
          case "CREATE_TODO": {
            this.createTodo(action.text);
            break;
          }
          case "DELETE_TODO": {
            this.deleteTodo(action.id);
            break;
          }
        }
      };
    }

推荐阅读