收到“ this.setState不是函数”错误

时间:2019-03-14 08:20:22

标签: javascript reactjs flux

我正在为基本的待办事项列表应用程序创建删除功能;但是,尝试从列表中删除某个项目并再次设置状态时遇到了问题。它不断给我一个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)

4 个答案:

答案 0 :(得分:2)

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

然后,我不会绑定这些函数,只是在您要在类中声明的每个函数中,我都将按照以下方式(在代码中指明您的方式)进行绑定:

nameOfFunction = () =>

使用这种形式(arrow function),您可以获得范围,因此可以使用它来访问状态。

最后,当您按下添加新元素时,这在React中被禁止。状态是不可变的,您只能创建一个新状态来进行任何更改,因此我们使用setState并帮助自己完成... this.state.todos(spread operator)。

它通过创建一个新数组并添加带有id和text的所需对象来实现。

希望我能对您有所帮助。 最好,

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

答案 1 :(得分:0)

出现此错误的原因是,您无法在类方法中访问该类的this对象。要解决此问题,请在要使用set state的构造函数中使用bind(this)

constructor(){
 super();
 this.state={};
 this.createTodo=this.createTodo.bind(this);
 this.deleteTodo=this.deleteTodo.bind(this);
 this.getAll=this.getAll.bind(this);
 this.handleActions=this.handleActions.bind(this);
}

您还可以使用箭头功能在函数内部使用此功能。 例如

createTodo = (text) => {

 }

答案 2 :(得分:0)

EventEmitter 类没有 this.setState 函数。如果要使用它,则必须位于React.Component中。

在这种情况下。我认为您可以在听发射-> 更改

setState

答案 3 :(得分:0)

如果该类未从React扩展Component,则不能使用setState。但是,您实际上并不需要setState,因为您所做的实际上只是“服务”而不是React组件。

您可以只使用自己的内部“状态”变量,可以将其称为todos,因为它仅包含待办事项列表。对于设置它,您不应该对其进行突变,而应从旧对象创建一个新对象并将其与新值合并:

this.todos = [ ...this.todos, { id, text } ]

或者您可以使用concat

this.todos = this.todos.concat({ id, text })

要删除的内容相同,只需使用过滤器即可。