ReactJS: e.preventDefault()不是一个函数

13

我正在制作一个简单的待办事项应用程序,我已经添加了编辑和删除待办事项的逻辑。我试图从子组件更新父状态,但当我尝试点击删除时,它会抛出错误e.preventDefault()不是函数,并且会删除所有待办事项。以下是组件:

父组件

export default class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
       listArr: [],
    }

  }


 deleteTodos(i) {
   var lists = this.state.listArr;
   lists.splice(i, 1);
   this.setState({listArr: lists})
 }

render() {
 .......
 <ToDoList {...this.state} passDeleteTodos={this.deleteTodos} />
......

}

儿童

export class ToDoList extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
              editing: false,
            };

        handleDelete(e, i) {
            e.preventDefault();
            this.props.passDeleteTodos()
        }


    renderDisplay() {
        return(
          <div>
           {
            this.props.listArr.map((list,i) => {
               return(
                 <div key={i} index={i} ref="text">
                  <li>{list}
                    <div style={{float: 'right'}}>
                     <button className="btn btn-danger btn-xs glyphicon glyphicon-trash"
                             onClick={() => this.handleDelete(i)}
                     />
                    </div>
                </div>
          </div>
6个回答

14

当你在实现中使用箭头函数时,需要将事件对象传递给handleDelete函数。你可以将箭头函数视为调用另一个需要传递参数的函数的函数。事件对象是箭头函数的参数,确实需要将其传递到handleDelete函数。

onClick={(e) => this.handleDelete(e, i)}

然而,在这个改变之后,你仍然需要在父组件中绑定deleteTodos函数,因为该函数内的this上下文不会是React类组件的上下文。你可以像这样做:

deleteTodos = (i) =>  {
   var lists = this.state.listArr;
   lists.splice(i, 1);
   this.setState({listArr: lists})
 }
或者
constructor(props){
    super(props);
    this.state = {
       listArr: [],
    }
    this.deleteTodos = this.deleteTodos.bind(this);
  }

1
这是因为您需要在父组件中绑定 deleteTodos 函数。 - Shubham Khatri
是的,只有在使用箭头函数时,将事件对象作为参数传递才有效,对吧? - Asche
正如我在答案中所描述的那样,箭头函数可以看作是调用另一个函数的函数,因此您需要传递参数。但是,在绑定的情况下,它会返回一个新函数,该函数已绑定上下文和您传递的参数以及默认参数。 - Shubham Khatri
哦,我现在明白了,谢谢Shubham,你真的很有帮助 :) - Asche

2

我改变了 e.preventDefault() => e.preventDefault 并使用 bind 绑定了函数。

示例

export default class App extends React.Component {
 constructor(props) {
   super(props)
   this.state = {
    listArr: [],
   }

  this.deleteTodos = this.deleteTodos.bind(this)

  }
  handleDelete(e, i) {
        e.preventDefault;
        this.props.passDeleteTodos()
        ...
    }

   render() {
    return(
      <div>
       {
        this.props.listArr.map((list,i) => {
           return(
             <div key={i} index={i} ref="text">
              <li>{list}
                <div style={{float: 'right'}}>
                 <button className="btn btn-danger btn-xs glyphicon glyphicon-trash"
                         onClick={(e,i) => this.handleDelete(e,i)}
                 />
                </div>
            </div>
       )}
      }
      </div>

0

你没有将e发送到相应的方法。

你也可以使用bind绑定事件:onClick={this.handleDelete.bind(this, i)}

App组件中的deleteTodos同样适用。

无论哪种方式,你都可以使用相同的方法或在构造函数中进行绑定:

export default class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
       listArr: [],
    }

    this.deleteTodos = this.deleteTodos.bind(this)
  }

  ...
}

0

不同于 a 标签,p 标签的行为不同,因此您不能期望相同的 preventDefault 调用。

但是您的问题在于绑定参数的顺序发生了改变。因此,您绑定的参数成为函数中的第一个参数。请参见下面的代码片段。

const App = () => {
  const _click = (externalVar, e) => {
    console.log("PARAMS", externalVar, e);
  };
  
  const externalVar = 1
  
  return (
    <button onClick={_click.bind(undefined, externalVar)}>click me</button>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

就像它所说的这里

fun.bind(thisArg[, arg1[, arg2[, ...]]])

arg1,arg2,...是在调用目标函数时要添加到绑定函数提供的参数之前预置的参数。

0
handleDelete(e, i) {
    e.preventDefault();
    this.props.passDeleteTodos()
    ...
}

onClick={(e,i) => this.handleDelete(e,i)}

如果上面的代码不能正常工作,请尝试这个。
handleDelete(i) {
    this.props.passDeleteTodos()
    ...
}

onClick={(e,i) => {e.preventDefault(); this.handleDelete(i)}}

你的第一个示例不完整,因为在调用handleDelete函数时,它没有接收到e参数。 - Hyetigran
代码已更新,首先,第一个对我也不起作用,但第二个可以。 - Rishan Nadeera

0

在React中,箭头函数不需要绑定this。 但是在调用函数时,例如调用handleDelete函数

 handleDelete(e, i) {
        e.preventDefault();
        this.props.passDeleteTodos()
    }

我们将使用以下语法:

handleDelete.bind(i)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接