2015-07-08 8 views
8

Jestem w trakcie aktualizacji komponentu React do ES6 i doznałem problemu opisanego w tym pytaniu - Unable to access React instance (this) inside event handler - a mianowicie braku powiązania z instancją składnika .React.js i ES6: Dowolne powody, dla których nie należy wiązać funkcji w konstruktorze

To miało sens i oczywiście działa, ale jestem mylić o drugiej części odpowiedź:

Należy pamiętać, że wiązanie funkcję tworzy nową funkcję. Możesz albo powiązać go bezpośrednio w render, co oznacza, że ​​nowa funkcja będzie tworzona za każdym razem, gdy komponent będzie renderować, lub wiązać ją w konstruktorze , który będzie uruchamiany tylko raz.

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

vs

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

jestem przy założeniu, że wiązanie w konstruktorze jest preferowanym podejściem do wykonywania etc, ale wiesz co mówią o zakładać!

Jakie są kompromisy dla tych dwóch podejść? Czy jest jakaś sytuacja, w której jedna jest zdecydowanie lepsza od drugiej? Czy to nie ma znaczenia?

Odpowiedz

11

Minus wiązania w konstruktorze: reaguj na hot loader nie działa.

Minusem wiązania w render(): wydajność.


Ostatnio robię to. Jest nieco szybszy niż wiązanie w renderowaniu, ale jestem skłonny wymienić wydajność na elastyczność i moją upragnioną wersję HMR.

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

Daje to nieco więcej elastyczności i łatwiejsze przejście do kanonicznego Atrybutu Wejściowego.

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

lub dodanie argumentów gdzie je ma:

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

Twój pierwszy punkt wystarczy, aby przekonać mnie do pozostawienia go w render(). Jeśli wydajność staje się problemem, zawsze mogę zamienić ją na produkcję. – MattDuFeu

+0

Nie używam programu hot-loader w moim projekcie, powinienem go użyć. Wszystkie wymagania wstępne (pakiet sieciowy, itp.) Są dostępne, chciałbym tylko wiedzieć, jakie główne ulepszenia mogę uzyskać dzięki programowi ładującemu? –

7

Myślę, że wszystko, co musisz zrozumieć, to Function.prototype.bind() zwróci nową funkcję. Zasadniczo będziesz wykonywał kreację za każdym razem, wykonując akcję wiązania w metodzie render(). Szanse na kilkakrotne wywołanie metody render() są naprawdę wysokie.

Robiąc to w konstruktorze, oznacza to, że kończysz wiązanie tylko raz i możesz użyć go tyle razy, ile chcesz. Nawet jeśli metoda render() zostanie wywołana wiele razy, zostanie użyta ta sama funkcja utworzona z innym kontekstem powiązania.

Tak, najlepiej powiąż w konstruktorze. Przypomina mi o piece of code (sprawdź konstruktora) przeżyłem kilka tygodni wstecz.

1

Sądzę, że udało Ci się rozwiązać główne problemy związane z odtwarzaniem funkcji. Chciałbym zaznaczyć inną opcję za pomocą funkcji strzałek i inicjalizatorów właściwości. Strzałka działa w tym przypadku automatycznie przyjmując lokalny this.

np.

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

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

Możesz przeczytać więcej na ten temat tutaj: http://babeljs.io/blog/2015/06/07/react-on-es6-plus/

Kiedy masz wiele funkcji, którą chcesz powiązać, to może być lepszym rozwiązaniem. Tracisz czystość tylko przy użyciu standardowej deklaracji funkcji.

+1

To może być wolniejszy niż .bind w konstruktorze, ponieważ musi tworzyć funkcje dla każdej instancji, a nie tylko .bind na tej samej funkcji . Ale oczywiście jest to prawdopodobnie pomijalne :-) – FakeRainBrigand

+0

Czy problem ten wystąpi, gdy natywne implementacje es6 pojawią się w przeglądarkach? Czy jest to tylko problem przy transporcie z es6 do es5? @FakeRainBrigand – rbhalla

+0

Cóż, to nie jest poprawne es6, więc ... dostaniesz błąd składni :-p Ale wydajność różni się między silnikami i wersjami tych silników, więc nie ma na to właściwej odpowiedzi. – FakeRainBrigand

Powiązane problemy