2015-07-08 14 views
8

Sono in procinto di aggiornare un componente React a ES6 e ho riscontrato il problema descritto in questa domanda - Unable to access React instance (this) inside event handler - vale a dire non vincolante per l'istanza del componente .React.js ed ES6: Qualsiasi motivo per non associare una funzione nel costruttore

Questo aveva un senso e, naturalmente, ha lavorato, ma sono confuso circa l'altra parte della risposta:

essere consapevoli del fatto che il legame di una funzione crea una nuova funzione. Puoi associarlo direttamente al rendering, il che significa che una nuova funzione sarà creata ogni volta che il componente esegue il rendering, o vincola nel tuo costruttore , che verrà attivato una sola volta.

constructor() { 
    this.changeContent = this.changeContent.bind(this); 
} 

vs

render() { 
    return <input onChange={this.changeContent.bind(this)} />; 
} 

sto supponendo che il legame nel costruttore è l'approccio preferito per le prestazioni, ecc, ma sai cosa dicono di assumere!

Quali sono i compromessi per questi due approcci? C'è mai una situazione in cui uno è decisamente migliore dell'altro? O non importa?

risposta

11

Lato negativo del collegamento nel costruttore: la reazione del caricatore caldo non funzionerà.

Lato negativo del binding in render(): performance.


Recentemente ho fatto questo. È leggermente più veloce rispetto al binding nel rendering, ma sono disposto a scambiare le prestazioni per la flessibilità e il mio ambito HMR.

render(){ 
    return <input onChange={(e) => this.handleChange(e.target.value)}>; 
} 

Offre un po 'più flessibilità, ad esempio, e una transizione più semplice all'atomo di input canonico.

render(){ 
    return <input onChange={(x) => this.handleChange(x)}>; 
} 

o l'aggiunta di argomenti dove vuoi:

render(){ 
    return (
    <ul> 
     {this.props.data.map((x, i) => { 
     // contrived example 
     return (
      <li 
      onMouseMove={(e) => this.handleMove(i, e.pageX, e.pageY)}> 
      {x} 
      </li> 
     ); 
     }} 
    </ul> 
); 
} 
+0

Il tuo primo punto è sufficiente per convincermi a lasciarlo in render(). Se le prestazioni diventano un problema, posso sempre scambiarlo per la produzione. – MattDuFeu

+0

Non sto usando hot-loader nel mio progetto, dovrei usarlo. Tutti i prerequisiti (webpack, ecc.) Ci sono, volevo solo sapere quali miglioramenti importanti posso ottenere con hot-loader? –

7

Penso che tutto quello che dovete capire è Function.prototype.bind() restituirà una nuova funzione. Quindi, in pratica, esegui ogni volta una creazione eseguendo l'azione di associazione nel metodo render(). La possibilità che il metodo render() venga chiamato più volte è davvero alto.

Così facendo nel costruttore significa che finisci per legare solo una volta e puoi riutilizzarlo tutte le volte che vuoi. Anche se il metodo render() viene chiamato più volte, verrà utilizzata la stessa funzione creata con un contesto associato diverso.

Sì, idealmente dovresti associarti al costruttore. Mi ricorda di un piece of code (controlla il costruttore) stavo passando un paio di settimane fa.

1

Penso che tu abbia risolto i problemi principali relativi alle funzioni di ricreazione. Vorrei evidenziare un'altra opzione usando le funzioni freccia e gli inizializzatori di proprietà. Le funzioni di freccia in questo caso adotteranno automaticamente lo this locale.

ad es.

class MyClass extends React.Component { 
    changeComponent = (e) => { 
    // this will refer to the component 
    } 

    render =() => { 
    return <input onChange={this.changeContent} />; 
    } 
} 

È possibile leggere di più qui: http://babeljs.io/blog/2015/06/07/react-on-es6-plus/

Quando si dispone di molte funzioni che ci si vuole legare, questo può essere una soluzione migliore. Tuttavia, perdi la pulizia di usare solo una dichiarazione di funzione standard.

+1

questo potrebbe essere più lento rispetto .bind nel costruttore perché deve creare le funzioni per ogni istanza invece di .bind sulla stessa funzione . Ma ovviamente questo è probabilmente trascurabile :-) – FakeRainBrigand

+0

Questo problema si presenterà quando le implementazioni native di es6 arrivano nei browser? O è solo un problema durante il transpiling da es6 a es5? @FakeRainBrigand – rbhalla

+0

Beh, questo non è valido es6 quindi ... riceverai un errore di sintassi :-p Ma le varianti di prestazioni tra motori e versioni di quei motori, quindi non c'è una risposta giusta a questo. – FakeRainBrigand

Problemi correlati