React onClick函数在渲染时触发


211

我将2个值传递给子组件:

  1. 要显示的对象列表
  2. 删除功能。

我使用.map()函数显示对象列表(如React教程页面中给出的示例中所示),但是该组件中的按钮在onClickrender上触发该函数(不应在渲染时触发)。我的代码如下所示:

module.exports = React.createClass({
    render: function(){
        var taskNodes = this.props.todoTasks.map(function(todo){
            return (
                <div>
                    {todo.task}
                    <button type="submit" onClick={this.props.removeTaskFunction(todo)}>Submit</button>
                </div>
            );
        }, this);
        return (
            <div className="todo-task-list">
                {taskNodes}
            </div>
        );
    }
});

我的问题是:为什么onClick函数在渲染时触发,如何使其不触发?

Answers:


528

因为您是在调用该函数而不是将函数传递给onClick,所以将该行更改为此:

<button type="submit" onClick={() => { this.props.removeTaskFunction(todo) }}>Submit</button>

=> 在ES6中引入了名为Arrow Function的功能,并将在React 0.13.3或更高版本中得到支持。


1
如何在咖啡中做到这一点?
vipin8169 '16

14
您也可以避免使用这些箭头功能花括号。我相信最好的做法是:onClick={() => this.props.removeTaskFn(todo)}
sospedra

1
您能再解释一下吗?我知道人们一直在说这不是最佳实践,但我想确切地了解()=>发生了什么。我理解箭头功能是什么,但不知道这是什么(),这为什么不好呢?
Wuno

@wuno()是您的匿名函数的参数。这里是空的,因为我们没有传入任何参数。假设()是function()的()。现在考虑为什么在render()函数中绑定不是最佳实践的原因是因为在每个渲染器上,我们都将函数重新绑定到组件,这可能会非常昂贵。
jaysonder

@LongNguyen这是我要找的东西!非常感谢
M.Wiśnicki19年

31

而不是调用函数,而是将值绑定到函数:

this.props.removeTaskFunction.bind(this, todo)

MDN参考:https//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind


2
恕我直言和许多其他。您应该优先使用无状态功能,而不要使用固定或绑定功能,因为这些功能可能会导致您出现不良后果。因此,即使两个答案都正确,我相信一个比另一个更合适。
sospedra

1
不建议在渲染器或组件中的其他任何位置直接绑定。绑定应该始终在构造函数中发生
Hemadri Dasari'Oct

15

onClick属性的值应该是一个函数,而不是函数调用。

<button type="submit" onClick={function(){removeTaskFunction(todo)}}>Submit</button>

8
不要在render内部的事件调用上使用匿名函数-它将触发另一个渲染
Splynx

4

对于那些不使用箭头功能但更简单的功能...在signOut函数后添加括号时遇到了此问题...

取代这个 <a onClick={props.signOut()}>Log Out</a>

与此<a onClick={props.signOut}>Log Out</a>...!😆


实际上,这根本不适合我。我传递了该函数,但从未添加括号,它仍然在渲染时触发。不知道自19年2月以来情况是否有所改变,但分配了Long Nguyen和Vishal Bisht的答案中的一个函数可以解决此问题。
BitShift

4

JSX与ReactJS一起使用,因为它与HTML非常相似,它使程序员有使用HTML的感觉,而最终却可以转换为javascript文件。

编写for循环并将函数指定为{this.props.removeTaskFunction(todo)}会在每次循环触发时执行这些函数。

要停止这种行为,我们需要将函数返回给onClick。

粗箭头功能具有一个隐藏的return语句以及bind属性。因此它会将函数返回给OnClick,因为Javascript也可以返回函数

用 -

onClick={() => { this.props.removeTaskFunction(todo) }}

意思是-

var onClick = function() {
  return this.props.removeTaskFunction(todo);
}.bind(this);

1

JSX将使用大括号评估JavaScript表达式

在这种情况下,this.props.removeTaskFunction(todo)被调用并将返回值分配给onClick

您需要提供的onClick是一个功能。为此,您可以将值包装在匿名函数中。

export const samepleComponent = ({todoTasks, removeTaskFunction}) => {
    const taskNodes = todoTasks.map(todo => (
                <div>
                    {todo.task}
                    <button type="submit" onClick={() => removeTaskFunction(todo)}>Submit</button>
                </div>
            );
    return (
        <div className="todo-task-list">
            {taskNodes}
        </div>
        );
    }
});

1

我有类似的问题,我的代码是:

function RadioInput(props) {
    return (
    <div className="form-check form-check-inline">
        <input className="form-check-input" type="radio" name="inlineRadioOptions" id={props.id} onClick={props.onClick} value={props.label}></input>
        <label className="form-check-label" htmlFor={props.id}>{props.label}</label>
    </div>
    );
  }
class ScheduleType extends React.Component
{
    renderRadioInput(id,label)
    {
        id = "inlineRadio"+id;
        return(
            <RadioInput
                id = {id}
                label = {label}
                onClick = {this.props.onClick}
            />
        );

    }

应该在哪里

onClick = {() => this.props.onClick()}

RenderRadioInput中

它为我解决了这个问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.