Obrasci reakcijskog vezanja: 5 pristupa za rukovanje `ovim`

JavaScript- ovo ponašanje ovih ključnih riječi zbunjuje programere već godinama.

Postoji najmanje pet načina za rješavanje ovog konteksta u Reactu. Razmotrimo zasluge svakog pristupa.

1. Upotrijebite React.createClass

Ako koristite React.createClass, Reagirati autobinds sve funkcije na to . Dakle, ova je ključna riječ automatski vezana za instancu vaše komponente:

// This magically works with React.createClass// because `this` is bound for you.onChange={this.handleChange}

Međutim, pojavom ES6 klasa, ovaj nestandardni pristup stvaranju klasa nije budućnost React-a. Zapravo će createClass vjerojatno biti izdvojen iz jezgre React u budućem izdanju.

2. Povežite u Render

Ostatak ovih pristupa pretpostavlja da deklarirate komponente React putem ES6 klasa. Ako koristite ES6 klasu, React se više ne veže. Jedan od načina da se to riješi je pozivanje veze u renderu:

onChange={this.handleChange.bind(this)}

Ovaj je pristup kratak i jasan, međutim, postoje implikacije na izvedbu jer se funkcija preraspodjeljuje na svaki prikaz. Ovo zvuči kao velika stvar, ali implikacije izvedbe ovog pristupa vjerojatno neće biti primjetne u većini aplikacija. Dakle, isključiti ovo na početku iz razloga performansi preuranjena je optimizacija. S tim u vezi, evo primjera gdje je utjecaj učinka na pristup bio važan.

U krajnjoj liniji, ako imate problema s performansama, izbjegavajte korištenje veza ili funkcija strelica u prikazivanju.

3. U renderu upotrijebite funkciju strelice

Ovaj pristup sličan je # 2. Promjenu ovog konteksta možete izbjeći upotrebom funkcije strelice u renderu:

onChange={e => this.handleChange(e)}

Ovaj pristup ima isti potencijalni učinak na izvedbu kao i # 2.

Vrijedno je razmotriti alternativne pristupe u nastavku jer nude vrhunske performanse uz malo dodatnih troškova.

4. Vezanje u konstruktoru

Jedan od načina da se izbjegne vezivanje u renderu je povezivanje u konstruktoru (drugi pristup je raspravljen u donjem dijelu 5).

constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); }

To je pristup koji se trenutno preporučuje u React dokumentima za "bolju izvedbu vaše aplikacije". To je također pristup koji koristim u "Izgradnji aplikacija s Reactom i Reduxom u ES6" na Pluralsightu.

Međutim, na većini aplikacija implikacije izvedbe pristupa br. 2 i br. 3 neće biti primjetne, pa prednosti čitljivosti i održavanja pristupa br. 2 i br. 3 mogu nadmašiti zabrinutost zbog performansi u mnogim aplikacijama.

Ali ako ste voljni koristiti značajke stupnja 2, posljednja opcija u nastavku vjerojatno će biti vaš najbolji ulog.

5. Upotrebite funkciju strelice u svojstvu klase

Ova se tehnika oslanja na predloženu značajku svojstva klase. Da biste koristili ovaj pristup, morate omogućiti svojstva-class-properties ili omogućiti stage-2 u Babelu.

handleChange = () => { // call this function from render // and this.whatever in here works fine. };

Ovaj pristup ima višestruke prednosti:

  1. Funkcije strelica prihvaćaju ovo vezanje obuhvaćajućeg opsega (drugim riječima, ne mijenjaju značenje ovoga), tako da stvari jednostavno rade automatski.
  2. Izbjegava probleme izvedbe pristupa br. 2 i 3.
  3. Izbjegava ponavljanje u pristupu # 4.
  4. Jednostavno je refaktorirati iz stila ES5 createClass u ovaj stil pretvaranjem relevantnih funkcija u funkcije strelica. U stvari, postoji potpuno automatiziran način da se to riješi pomoću kodnog moda.

Sažetak

Ovaj dijagram toka koji sažima odluku.

Evo cjelovitih radnih primjera svih 5 pristupa:

// Approach 1: Use React.createClass var HelloWorld = React.createClass({ getInitialState() { return { message: 'Hi' }; }, logMessage() { // this magically works because React.createClass autobinds. console.log(this.state.message); }, render() { return (  ); } }); // Approach 2: Bind in Render class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { message: 'Hi' }; } logMessage() { // This works because of the bind in render below. console.log(this.state.message); } render() { return (  ); } } // Approach 3: Use Arrow Function in Render class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { message: 'Hi' }; } logMessage() { // This works because of the arrow function in render below. console.log(this.state.message); } render() { return (  this.logMessage()} /> ); } } // Approach 4: Bind in Constructor class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { message: 'Hi' }; this.logMessage = this.logMessage.bind(this); } logMessage() { // This works because of the bind in the constructor above. console.log(this.state.message); } render() { return (  ); } } // Approach 5: Arrow Function in Class Property class HelloWorld extends React.Component { // Note that state is a property, // so no constructor is needed in this case. state = { message: 'Hi' }; logMessage = () => { // This works because arrow funcs adopt the this binding of the enclosing scope. console.log(this.state.message); }; render() { return (  ); } }

Pa što ljudi više vole? Evo ankete:

Kako danas rješavate vezanje u #reactjs-u?

Primjeri: //t.co/z7OKxe39VA

- Cory House (@housecor) 18. kolovoza 2016

Imate li druge načine kako to riješiti? Molimo vas da nazovete putem komentara.

Ogromna hvala @dan_abramov, @kentcdodds i @dmosher na njihovom vrijednom doprinosu i recenziji!

Cory House autor je knjiga "Izgradnja aplikacija s Reactom i Reduxom u ES6", "Izgradnja aplikacija s Reactom i Fluxom", "Čisti kôd: Pisanje koda za ljude" i mnogim drugim tečajevima o Pluralsightu. On je softverski arhitekt u tvrtki VinSolutions, Microsoft MVP, i međunarodno razvija programere softverskih praksi poput front-end razvoja i čistog kodiranja.