我正在为我的基本待办事项列表应用程序创建删除功能;但是当我尝试从列表中删除某个项目并再次设置状态时遇到了问题。它继续给我一个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)
首先,我将该类声明为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;
}
}
};
}
您收到此错误的原因是您无法访问类方法中类的此对象。要克服此问题,请在构造函数中使用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) => {
}
EventEmitter类没有this.setState函数。如果要使用它,则必须位于React.Component中。
在这种情况下。我认为你在收听emit - > change时可以设置setState
如果类没有从React扩展Component,则不能使用setState
。但是,你在这里并不需要setState,因为你所做的实际上只是一个“服务”,而不是一个React组件。
您可以使用自己的内部“状态”变量,您可以将其称为todos
,因为它只包含待办事项列表。为了设置它,你不应该改变它,而是从旧的对象创建一个新对象并将其与新值合并:
this.todos = [ ...this.todos, { id, text } ]
或者你可以使用concat
:
this.todos = this.todos.concat({ id, text })
删除同样的事情,你只需使用过滤器。