2016-04-13 26 views
5

Pracuję nad implementacją przeciągania i upuszczania (od zera, bez użycia biblioteki DND) i chciałem ograniczyć liczbę niepotrzebnych aktualizacji podczas przeciągania.Reakcja: Najlepszy sposób na aktualizację siebie, ale uniemożliwić dzieciom aktualizację?

Przeciąganie "klonu" (który zwykle jest kopią oryginalnego elementu, ale może być dowolnym elementem zastępczym), uzyskuje się poprzez aktualizację stanu komponentu kontenera ("Clonetainer") i użycie go do zastosowania przekształcenia . Nie ma jednak sensu aktualizować całego poddrzewa podczas ruchu, ponieważ jedyną zmianą jest współrzędne kontenera.

Oto moje rozwiązanie, że:

const ClonetainerRenderShield = React.createClass({ 
    shouldComponentUpdate: function (newProps) { 
     return newProps.shouldUpdate; 
    }, 
    render: function() { 
     return this.props.children; // Simple pass-through 
    } 
}); 

const Clonetainer = React.createClass({ 
    componentWillReceiveProps: function (newProps) { 
     // OR in any further properties that may indicate a move, versus a child update 
     this.isMoveEvent = this.props.offset !== newProps.offset; 
    }, 
    render: function() { 
     const style = { transform: `translate(${this.props.offset.left}px,${this.props.offset.top}px)` }; 
     return <div className="clonetainer-div" style={style}> 
      <ClonetainerRenderShield shouldUpdate={ !this.isMoveEvent }> 
       { this.props.children } 
      </ClonetainerRenderShield> 
     </div>; 
    } 
}); 

(nie będę wchodził w szczegóły na resztę systemu DND, z wyjątkiem powiedzieć, że zdarzenia myszy z górnego elementu karmić offsetu param do Clonetainer.)

rozwiązanie wpadłem do zatrzymania aktualizację zaangażowany określenia, czy Clonetainer został wywołany do aktualizacji ze względu na ruch lub jakiegoś innego powodu (i ustawienie this.isMoveEvent odpowiednio), a następnie podkładek komponentu pomiędzy Clonetainer a dzieci składające się wyłącznie z funkcji shouldComponentUpdate opartej na podany rekwizyt (shouldUpdate).

To działa. Przetestowałem to w sposób, który pokazuje, że aktualizuje się, kiedy powinien i nie aktualizuje, kiedy nie powinien, ale czuje się trochę jak przesada, by mieć oddzielny komponent shim, po prostu blokujący aktualizację, płynącą w dół. Czy istnieje sposób, aby wskazać, że komponent potomny nie powinien być aktualizowany z poprzedniego stanu w render, bez wymagania komponentu podrzędnego do włączenia jego własnej logiki shouldComponentUpdate?

+3

Myślę, że twoje podejście jest poprawne, a najlepsze dostępne. Innym podejściem byłoby manipulowanie bezpośrednio węzłem DOM dla 'Clonetainer' podczas przeciągania. – VonD

Odpowiedz

1

Powinieneś być w stanie zmienić componentWillReceiveProps na shouldComponentUpdate w komponencie Clonetainer i wyciąć środkowego człowieka. shouldComponentUpdate pobiera dwa parametry, (object nextProps, object nextState), których można użyć do porównania wartości this.state i this.props. Zwrócenie wartości true spowoduje ponowne renderowanie.

const Clonetainer = React.createClass({ 
    shouldComponentUpdate: function (nextProps, nextState) { 
     // OR in any further properties that may indicate a move, versus a child update 
     this.props.offset !== nextProps.offset; 
    }, 
    render: function() { 
     const style = { transform: `translate(${this.props.offset.left}px,${this.props.offset.top}px)` }; 
     return <div className="clonetainer-div" style={style}> 
      { this.props.children } 
     </div>; 
    } 
}); 
+0

To nie pozwoliłoby mi zmienić pozycji na Clonetainerze, prawda? Problem, który pojawił się, gdy pozycja Clonetainer musi się zmienić (musi być ponownie renderowana), ale żadna z danych zawartości nie ma (więc nie powinny). Przy pomocy funkcji shouldComponentUpdate oczekuję, że uzyskasz "wszystkie" (funkcja shouldComponentUpdate zwróci wartość true, a całe drzewo zostanie ponownie wygenerowane) lub "nothing" (funkcja shouldComponentUpdate zwróci wartość false i nic się nie zmieni). – SuperFLEB

Powiązane problemy