Reacciona la función onClick dispara en render

212

Le paso 2 valores a un componente hijo:

  1. Lista de objetos para mostrar
  2. Eliminar función.

Utilizo una función .map () para mostrar mi lista de objetos (como en el ejemplo dado en la página tutorial de reacción), pero el botón en ese componente activa la onClickfunción, en el renderizado (no debe activarse en el tiempo de renderizado). Mi código se ve así:

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>
        );
    }
});

Mi pregunta es: ¿por qué la onClickfunción se activa en el render y cómo hacer que no lo haga?

Stralos
fuente

Respuestas:

528

Debido a que está llamando a esa función en lugar de pasar la función a onClick, cambie esa línea a esto:

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

=> llamado Función de flecha, que se introdujo en ES6, y será compatible con React 0.13.3 o superior.

Long Nguyen
fuente
1
¿Cómo hacer esto en Coffescript?
vipin8169
14
También puede evitar estas llaves con función de flecha. Lo que creo coincide con las mejores prácticas:onClick={() => this.props.removeTaskFn(todo)}
sospedra
1
¿Podría explicar esto un poco más? Entiendo que la gente sigue diciendo que no es la mejor práctica, pero me gustaría entender qué está sucediendo aquí exactamente con () => Entiendo qué es una función de flecha pero no qué es esto () y por qué esto es malo.
wuno
@wuno El () son los parámetros de su función anónima. Está vacío aquí porque no estamos pasando ningún parámetro. Imagine que el () es el () de la función (). Ahora, por qué no es la mejor práctica para el enlace en la función render () es porque en cada render, estamos volviendo a vincular la función al componente, lo que puede ser muy costoso.
jaysonder
@LongNguyen ¡Esto es lo que estoy buscando! muchas gracias
M. Wiśnicki
31

En lugar de llamar a la función, vincule el valor a la función:

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

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

Pete TNT
fuente
2
En mi humilde opinión y muchos otros. Debes favorecer las funciones sin estado sobre la clase o la vinculación porque pueden llevarte a efectos secundarios no deseados. Por lo tanto, aun siendo ambas respuestas correctas, creo que una es más apropiada que la otra.
sospedra
1
No se recomienda el enlace directo en render o en cualquier otro lugar del componente. El enlace debe suceder siempre en el constructor
Hemadri Dasari
15

El valor de su onClickatributo debe ser una función, no una llamada a función.

<button type="submit" onClick={function(){removeTaskFunction(todo)}}>Submit</button>
Brian Swisher
fuente
8
No utilice funciones anónimas en las llamadas de evento dentro del renderizado: activará otro renderizado
Splynx
4

Para aquellos que no usan funciones de flecha pero algo más simple ... Encontré esto al agregar paréntesis después de mi función signOut ...

reemplazar esto <a onClick={props.signOut()}>Log Out</a>

con esto <a onClick={props.signOut}>Log Out</a>...! 😆

olisteadman
fuente
En realidad eso no me funciona en absoluto. Pasé la función y nunca agregué paréntesis y todavía se disparó en render. No estoy seguro de si esto ha cambiado desde febrero de 19, pero la asignación de una función como en la respuesta de Long Nguyen y Vishal Bisht solucionó el problema.
BitShift
4

JSX se usa con ReactJS, ya que es muy similar al HTML y les da a los programadores la sensación de usar HTML, mientras que finalmente se transpira en un archivo javascript.

Escribir una función for-loop y especificar como {this.props.removeTaskFunction (todo)} ejecutará las funciones cada vez que se active el bucle.

Para detener este comportamiento, necesitamos devolver la función a onClick.

La función de flecha gruesa tiene una declaración de retorno oculta junto con la propiedad de vinculación . ¡Por lo tanto, devuelve la función a OnClick ya que Javascript también puede devolver funciones !

Utilizar -

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

lo que significa-

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

JSX evaluará expresiones de JavaScript en llaves

En este caso, this.props.removeTaskFunction(todo)se invoca y el valor de retorno se asigna aonClick

Lo que tienes que proporcionar onClickes una función. Para hacer esto, puede ajustar el valor en una función anónima.

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>
        );
    }
});
sudo bangbang
fuente
1

Tuve un problema similar, mi código fue:

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}
            />
        );

    }

Donde debería estar

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

en RenderRadioInput

Me solucionó el problema.

Seyhak Ly
fuente