Bearbeiten 2018: Jetzt hat React Unterstützung für Context
Ich werde versuchen, eine generische Antwort zu geben, die dieses spezifische Problem und auch ein allgemeineres Problem anspricht.
Wenn Sie sich nicht um Nebeneffekte von Bibliotheken kümmern, können Sie einfach etwas wie Packery verwenden.
Wenn Sie Flux verwenden, könnten Sie einen Store erstellen, der die Fenstereigenschaften enthält, sodass Sie eine reine Renderfunktion beibehalten können, ohne jedes Mal das Fensterobjekt abfragen zu müssen.
In anderen Fällen, in denen Sie eine responsive Website erstellen möchten, jedoch React-Inline-Styles anstelle von Media Queries bevorzugen oder das HTML/JS-Verhalten entsprechend der Fensterbreite ändern möchten, lesen Sie weiter:
Was ist React-Context und warum ich darüber spreche
React-Context ist nicht Teil der öffentlichen API und ermöglicht es, Eigenschaften an eine ganze Hierarchie von Komponenten weiterzugeben.
React-Context ist besonders nützlich, um Dinge an Ihre gesamte App weiterzugeben, die sich nie ändern (es wird von vielen Flux-Frameworks über ein Mixin verwendet). Sie können es verwenden, um App-Geschäftsinvarianzen zu speichern (wie die verbundene Benutzer-ID, damit sie überall verfügbar ist).
Aber es kann auch verwendet werden, um Dinge zu speichern, die sich ändern können. Das Problem ist, dass, wenn sich der Kontext ändert, alle Komponenten, die ihn verwenden, neu gerendert werden sollten, und es ist nicht einfach, dies zu tun. Die beste Lösung besteht oft darin, die gesamte App mit dem neuen Kontext zu demontieren/wiederzuinstallieren. Denken Sie daran, dass forceUpdate nicht rekursiv ist.
Wie Sie verstehen, ist der Kontext praktisch, aber es gibt eine Leistungsauswirkung, wenn er sich ändert, daher sollte er lieber nicht zu oft geändert werden.
Was in den Kontext stellen
- Invarianzen: wie die verbundene Benutzer-ID, die Sitzungstoken, was auch immer...
- Dinge, die sich nicht oft ändern
Hier sind Dinge, die sich nicht oft ändern:
Die aktuelle Benutzersprache:
Es ändert sich nicht sehr oft, und wenn es das tut, da die gesamte App übersetzt wird, müssen wir alles neu rendern: ein sehr schönes Anwendungsfallszenario für einen heißen Sprachwechsel
Die Fenstereigenschaften
Breite und Höhe ändern sich nicht oft, aber wenn wir unser Layout und Verhalten anpassen müssen. Für das Layout ist es manchmal einfach, mit CSS-Mediaqueries anzupassen, aber manchmal ist es nicht und erfordert eine andere HTML-Struktur. Für das Verhalten müssen Sie dies mit Javascript behandeln.
Sie möchten nicht alles bei jedem Größenänderungsevent neu rendern, also müssen Sie die Größenänderungsevents drosseln.
Was ich von Ihrem Problem verstehe, ist, dass Sie wissen möchten, wie viele Elemente je nach Bildschirmbreite angezeigt werden sollen. Also müssen Sie zunächst reaktionsfähige Breakpoints definieren und die Anzahl der verschiedenen Layouttypen angeben, die Sie haben können.
Zum Beispiel:
- Layou "1 Spalte", für Breite <= 600
- Layout "2 Spalten", für 600 < Breite < 1000
- Layout "3 Spalten", für 1000 <= Breite
Bei Größenänderungsevents (gedrosselt) können Sie den aktuellen Layouttyp problemlos abrufen, indem Sie das Fensterobjekt abfragen.
Dann können Sie den Layouttyp mit dem früheren Layouttyp vergleichen, und wenn er sich geändert hat, die App mit einem neuen Kontext neu rendern: Dadurch wird vermieden, dass die App überhaupt neu gerendert wird, wenn der Benutzer Größenänderungsevents ausgelöst hat, aber tatsächlich der Layouttyp nicht geändert wurde. So rendern Sie nur bei Bedarf neu.
Wenn Sie das haben, können Sie einfach den Layouttyp innerhalb Ihrer App verwenden (zugänglich durch den Kontext), sodass Sie das HTML, Verhalten, CSS-Klassen... anpassen können. Sie kennen Ihren Layouttyp innerhalb der React-Renderfunktion, was bedeutet, dass Sie problemlos responsive Websites durch Verwenden von Inline-Styles schreiben können und überhaupt keine Media-Queries benötigen.
Wenn Sie Flux verwenden, können Sie anstelle von React-Context einen Store verwenden, aber wenn Ihre App viele reaktionsfähige Komponenten hat, ist es vielleicht einfacher, Context zu verwenden?