La funzione React onClick si attiva al rendering


212

Passo 2 valori a un componente figlio:

  1. Elenco di oggetti da visualizzare
  2. funzione di eliminazione.

Uso una funzione .map () per visualizzare il mio elenco di oggetti (come nell'esempio riportato nella pagina del tutorial di reazione), ma il pulsante in quel componente onClickattiva la funzione, al rendering (non dovrebbe attivarsi al tempo di rendering). Il mio codice è simile al seguente:

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

La mia domanda è: perché la onClickfunzione si attiva sul rendering e come evitarlo?

Risposte:


528

Poiché stai chiamando quella funzione invece di passare la funzione a onClick, cambia quella linea in questo:

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

=> chiamata Arrow Function, introdotta in ES6, e sarà supportata su React 0.13.3 o versioni successive.


1
come fare questo in caffettiera?
vipin8169,

14
È possibile evitare anche queste parentesi graffe con funzione freccia. Che credo corrisponda alle migliori pratiche:onClick={() => this.props.removeTaskFn(todo)}
sospedra,

1
Potresti spiegarlo un po 'di più? Capisco che la gente continui a dire che non è la migliore pratica, ma vorrei capire cosa sta succedendo qui esattamente con () => Capisco cos'è una funzione freccia ma non di cosa si tratta () e perché questo è negativo?
martedì

@wuno Il () è i parametri della tua funzione anonima. È vuoto qui perché non stiamo passando alcun parametro. Immagina che il () sia il () della funzione (). Ora, per quanto riguarda il motivo per cui non è la migliore pratica per il binding nella funzione render () è perché su ogni rendering, stiamo vincolando la funzione al componente, che può essere molto costoso.
jaysonder,

@LongNguyen Questo è quello che sto cercando! grazie mille
M. Wiśnicki il

31

Invece di chiamare la funzione, associare il valore alla funzione:

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

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


2
IMHO e molti altri. Dovresti favorire le funzioni apolidi rispetto al clasess o all'associazione perché possono portare a effetti collaterali indesiderati. Pertanto, pur essendo entrambe le risposte corrette, credo che uno sia più apporpato dell'altro.
sospedra,

1
L'associazione diretta nel rendering o in qualsiasi altra parte del componente non è consigliata. Il legame dovrebbe avvenire sempre nel costruttore
Hemadri Dasari,

15

Il valore per l' onClickattributo dovrebbe essere una funzione, non una chiamata di funzione.

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

8
Non utilizzare funzioni anonime per le chiamate agli eventi all'interno del rendering - innescherà un altro rendering
Splynx

4

Per coloro che non usano le funzioni freccia ma qualcosa di più semplice ... L'ho riscontrato durante l'aggiunta di parentesi dopo la mia funzione signOut ...

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

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


In realtà non funziona affatto per me. Ho trasmesso la funzione e non ho mai aggiunto la parentesi e si è comunque attivato il rendering. Non sono sicuro che questo sia cambiato dal febbraio '19, ma l'assegnazione di una funzione come nella risposta di Long Nguyen e Vishal Bisht ha risolto il problema.
BitShift

4

JSX è usato con ReactJS in quanto è molto simile all'HTML e dà ai programmatori la sensazione di usare l'HTML mentre alla fine si traspila in un file javascript.

Scrivendo una funzione for-loop e specificando come {this.props.removeTaskFunction (todo)} verranno eseguite le funzioni ogni volta che viene attivato il loop.

Per interrompere questo comportamento, è necessario riportare la funzione su onClick.

La funzione freccia grassa ha un'istruzione return nascosta insieme alla proprietà bind . Quindi restituisce la funzione a OnClick poiché anche Javascript può restituire funzioni !!!!!

Uso -

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

che significa-

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

1

JSX valuterà le espressioni JavaScript tra parentesi graffe

In questo caso, this.props.removeTaskFunction(todo)viene invocato e viene assegnato il valore restituitoonClick

Quello che devi fornire onClickè una funzione. Per fare ciò, è possibile racchiudere il valore in una funzione anonima.

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

Ho avuto un problema simile, il mio codice era:

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

    }

Dove dovrebbe essere

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

in RenderRadioInput

Mi ha risolto il problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.