Получение ошибки «this.setState не является функцией» - PullRequest
0 голосов
/ 14 марта 2019

Я создаю функцию удаления для моего основного приложения списка задач; Однако я столкнулся с проблемой при попытке удалить определенный элемент из списка и снова установить состояние. Он продолжает выдавать мне ошибку 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 ]

2 голосов
/ 14 марта 2019

Прежде всего, я объявил бы класс как React Component, без этого вы не сможете иметь «состояние» и не сможете получить доступ к функции setState (которая является той, которая создает новое состояние). ).

Тогда я бы не связывал функции, просто в каждой из функций, которые вы хотели бы объявить внутри класса, я сделал бы это следующим образом, как я вам указал в коде:

nameOfFunction = () =>

С помощью этой формы ( функция стрелки ) вы получаете область и, следовательно, сможете использовать ее для доступа к состоянию.

Наконец, когда вы нажимаете, чтобы добавить новый элемент, это ЗАПРЕЩЕНО в React. Состояние является неизменным, и вы можете создать новое состояние только для внесения любых изменений, поэтому мы используем setState и помогаем себе ... this.state.todos ( оператор распространения ).

Это делается путем создания нового массива и добавления нужного вам объекта с идентификатором и текстом.

Я надеюсь, что помог вам. Лучшее,

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 голосов
/ 14 марта 2019

Вы не можете использовать setState, если класс не расширяет Компонент из React.Тем не менее, вам не нужно использовать setState здесь, так как на самом деле вы всего лишь «сервис», а не компонент React.

Вы можете просто использовать свою собственную внутреннюю переменную «состояние», вы можете вызвать ееtodos, поскольку он содержит только список задач.Для его установки вам не следует изменять его, а создавать новый объект из старого и объединять его с новыми значениями:

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

Или вы можете использовать concat:

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

То же самое для удаления, вы просто используете фильтр.

0 голосов
/ 14 марта 2019

EventEmitter класс не имеет функции this.setState .Если вы хотите использовать это, вы должны быть в React.Component.

В кейсе.Я думаю, что вы можете setState когда вы слушаете Emit -> изменить

0 голосов
/ 14 марта 2019

Причина, по которой вы получаете эту ошибку, заключается в том, что вы не получаете доступ к объекту this класса внутри методов класса. Чтобы преодолеть это, используйте 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) => {

 }
...