Ich habe eine App, in der ich die Höhe eines Elements (sagen wir "App-Inhalt") dynamisch einstellen muss. Es nimmt die Höhe des "Chroms" der App und subtrahiert sie und legt dann die Höhe des "App-Inhalts" so fest, dass sie zu 100% in diese Einschränkungen passt. Dies ist mit Vanilla JS-, jQuery- oder Backbone-Ansichten sehr einfach, aber ich habe Schwierigkeiten herauszufinden, wie der richtige Prozess dafür in React aussehen würde.
Unten finden Sie eine Beispielkomponente. Ich möchte in der Lage sein, die app-content
Höhe des Fensters auf 100% des Fensters abzüglich der Größe des ActionBar
und einzustellen BalanceBar
, aber woher weiß ich, wann alles gerendert wird und wo ich das Berechnungsmaterial in diese Reaktionsklasse einfügen würde?
/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
module.exports = AppBase;
javascript
reactjs
Oscar Patensohn
quelle
quelle
Antworten:
componentDidMount ()
Diese Methode wird einmal aufgerufen, nachdem Ihre Komponente gerendert wurde. Ihr Code würde also so aussehen.
quelle
componentDidUpdate
wenn sich die Werte nach dem ersten Rendern ändern können.componentDidMount()
bewirkt das Ändern des CSS keinen Übergang.componentDidMount: () => { setTimeout(addClassFunction())}
oder verwenden Sie rAF, die Antwort darunter liefert diese Antwort.Ein Nachteil der Verwendung von
componentDidUpdate
odercomponentDidMount
besteht darin, dass sie tatsächlich ausgeführt werden, bevor die dom-Elemente gezeichnet werden, aber nachdem sie von React an das DOM des Browsers übergeben wurden.Angenommen, Sie müssen node.scrollHeight auf das gerenderte node.scrollTop setzen, dann reichen die DOM-Elemente von React möglicherweise nicht aus. Sie müssen warten, bis die Elemente fertig gestrichen sind, um ihre Höhe zu erhalten.
Lösung:
Verwenden Sie
requestAnimationFrame
diese Option, um sicherzustellen, dass Ihr Code nach dem Malen Ihres neu gerenderten Objekts ausgeführt wirdquelle
_this.getDOMNode is not a function
Was zum Teufel ist dieser Code?Nach meiner Erfahrung
window.requestAnimationFrame
war es nicht genug, um sicherzustellen, dass das DOM vollständig gerendert / reflow-vollständig von warcomponentDidMount
. Ich habe Code ausgeführt, der unmittelbar nach einemcomponentDidMount
Aufruf auf das DOM zugreift und dessen alleinige Verwendung dazu führenwindow.requestAnimationFrame
würde, dass das Element im DOM vorhanden ist. Aktualisierungen der Abmessungen des Elements werden jedoch noch nicht berücksichtigt, da noch kein Reflow aufgetreten ist.Die einzig wirklich zuverlässige Möglichkeit, dies zu erreichen, bestand darin, meine Methode in a
setTimeout
und a zu verpacken,window.requestAnimationFrame
um sicherzustellen, dass der aktuelle Aufrufstapel von React gelöscht wird, bevor Sie sich für das Rendern des nächsten Frames registrieren.Wenn ich darüber spekulieren müsste, warum dies auftritt / notwendig ist, könnte ich React Batching DOM-Updates sehen und die Änderungen erst nach Abschluss des aktuellen Stacks auf das DOM anwenden.
Wenn Sie DOM-Messungen in dem Code verwenden, den Sie nach den React-Rückrufen auslösen, möchten Sie wahrscheinlich diese Methode verwenden.
quelle
Um diese Frage mit den neuen Hook-Methoden ein wenig zu aktualisieren, können Sie einfach den
useEffect
Hook verwenden:Auch wenn Sie vor dem Layout malen möchten, verwenden Sie den
useLayoutEffect
Haken:quelle
Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
ich bearbeiten werde.Sie können den Status ändern und dann Ihre Berechnungen im setState-Rückruf durchführen . Laut der React-Dokumentation wird "garantiert ausgelöst, nachdem das Update angewendet wurde".
Dies sollte im
componentDidMount
oder an einer anderen Stelle im Code (wie bei einem Ereignishandler zur Größenänderung) und nicht im Konstruktor erfolgen.Dies ist eine gute Alternative zu
window.requestAnimationFrame
und es gibt nicht die Probleme, die einige Benutzer hier erwähnt haben (sie müssen mit kombiniertsetTimeout
oder mehrmals aufgerufen werden). Zum Beispiel:quelle
Ich finde, dass diese Lösung schmutzig ist, aber los geht's:
Jetzt sitze ich einfach hier und warte auf die Abstimmungen.
quelle
React verfügt nur über wenige Lebenszyklusmethoden, die in diesen Situationen hilfreich sind. Die Listen umfassen unter anderem getInitialState, getDefaultProps, componentWillMount, componentDidMount usw.
In Ihrem Fall und in den Fällen, die mit den DOM-Elementen interagieren müssen, müssen Sie warten, bis der Dom bereit ist. Verwenden Sie also componentDidMount wie folgt :
Weitere Informationen zum Lebenszyklus in Reaktion finden Sie unter folgendem Link: https://facebook.github.io/react/docs/state-and-lifecycle.html
quelle
Ich bin auf das gleiche Problem gestoßen.
In den meisten Szenarien mit dem Hack-ish
setTimeout(() => { }, 0)
incomponentDidMount()
gearbeitet.Aber nicht in einem besonderen Fall; und ich wollte das nicht verwenden,
ReachDOM findDOMNode
da in der Dokumentation steht:(Quelle: findDOMNode )
In dieser speziellen Komponente musste ich das
componentDidUpdate()
Ereignis verwenden, sodass mein Code folgendermaßen aussah:Und dann:
Schließlich musste ich in meinem Fall den Listener entfernen, der in erstellt wurde
componentDidMount
:quelle
Nach dem Rendern können Sie die Höhe wie unten angeben und die Höhe für die entsprechenden Reaktionskomponenten angeben.
oder Sie können die Höhe jeder Reaktionskomponente mit sass angeben. Geben Sie die ersten 2 Reaktionskomponenten-Hauptdivs mit fester Breite und dann die Höhe der dritten Komponentenhauptdivs mit Auto an. Basierend auf dem Inhalt des dritten Div wird die Höhe zugewiesen.
quelle
Ich habe tatsächlich Probleme mit einem ähnlichen Verhalten. Ich rendere ein Videoelement in einer Komponente mit dem ID-Attribut. Wenn RenderDOM.render () beendet wird, wird ein Plugin geladen, das die ID benötigt, um den Platzhalter zu finden, und es kann ihn nicht finden.
Das setTimeout mit 0ms innerhalb der componentDidMount () hat es behoben :)
quelle
Aus der Dokumentation zu ReactDOM.render () :
quelle
ReactDOM.render
EbeneReactElement.render
verfügbar , nicht für die Komponentenebene (die hier Gegenstand ist).Für mich keine Kombination von
window.requestAnimationFrame
odersetTimeout
konsistente Ergebnisse. Manchmal funktionierte es, aber nicht immer - oder manchmal war es zu spät.Ich habe es behoben, indem ich
window.requestAnimationFrame
so oft wie nötig eine Schleife gemacht habe .(Normalerweise 0 oder 2-3 mal)
Der Schlüssel ist
diff > 0
: Hier können wir genau sicherstellen, wann die Seite aktualisiert wird.quelle
Ich hatte eine seltsame Situation, als ich eine Reaktionskomponente drucken musste, die große Datenmengen empfängt und auf Leinwand malt. Ich habe alle genannten Ansätze ausprobiert, von denen keiner für mich zuverlässig funktioniert hat. Mit requestAnimationFrame in setTimeout erhalte ich in 20% der Fälle eine leere Leinwand, also habe ich Folgendes getan:
Grundsätzlich habe ich eine Kette von requestAnimationFrames erstellt. Ich bin mir nicht sicher, ob dies eine gute Idee ist oder nicht, aber dies funktioniert bisher in 100% der Fälle für mich (ich verwende 30 als Wert für die Variable n).
quelle
Es gibt tatsächlich eine viel einfachere und sauberere Version als die Verwendung von Anforderungsanimationsrahmen oder Zeitüberschreitungen. Ich bin überrascht, dass niemand darauf eingegangen ist: der Vanilla-Js-Onload-Handler. Wenn Sie können, verwenden Sie component did mount. Wenn nicht, binden Sie einfach eine Funktion an den Onload-Hanlder der jsx-Komponente. Wenn Sie möchten, dass die Funktion jedes Rendern ausführt, führen Sie sie auch aus, bevor Sie die Ergebnisse in der Renderfunktion zurückgeben. Der Code würde so aussehen:
}}
quelle
Ein bisschen Update mit
ES6
Klassen stattReact.createClass
Überprüfen Sie auch die Methoden zum Reagieren des Komponentenlebenszyklus: Der Komponentenlebenszyklus
Jede Komponente hat viele ähnliche Methoden wie
componentDidMount
z.componentWillUnmount()
- Die Komponente wird aus dem Browser-DOM entferntquelle