获取“this.setState不是函数”错误

问题描述 投票:0回答:4

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

0
投票

您收到此错误的原因是您无法访问类方法中类的此对象。要克服此问题,请在构造函数中使用bind(this),以便使用set state。

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) => {

 }

0
投票

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

在这种情况下。我认为你在收听emit - > change时可以设置setState


0
投票

如果类没有从React扩展Component,则不能使用setState。但是,你在这里并不需要setState,因为你所做的实际上只是一个“服务”,而不是一个React组件。

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

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

或者你可以使用concat

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

删除同样的事情,你只需使用过滤器。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.