React: [Regenschirm] Spannung freisetzen

Erstellt am 13. Juli 2018  ·  83Kommentare  ·  Quelle: facebook/react

Lassen Sie uns dieses Problem verwenden, um die verbleibenden Aufgaben für die Freigabe von Suspense für Open Source zu verfolgen.

Erstveröffentlichung (MVP)

Kern

  • [x] API zum Lesen von Kontext aus einer beliebigen Renderphasenfunktion (@acdlite) [#13139]
  • [x] Inhalte mit Zeitüberschreitung ausblenden statt löschen (@acdlite) [#13120]
  • [ ] Automatische Injektion von Kontextanbietern pro React-Root (@acdlite) [#13293]
  • [ ] unstable_ Präfix von AsyncMode entfernen (vielleicht?)
  • [ ] Unterstützung für synchrone Thenables und für Promises, die aufgelöst werden, bevor die Renderphase abgeschlossen ist.

    • [ ] Bestätigen Sie, dass ein synchrones Thenable, das einen Fehler auslöst, korrekt behandelt wird

  • [ ] Bestätige mit <div hidden> [#13089]
  • [ ] Warum führt das Anklicken mehrerer Detaillinks im Gerät nacheinander schließlich zu einem großen Platzhalter, auch wenn ich auf jeden von ihnen weniger als die Platzhalterverzögerung warte, bevor ich auf den nächsten klicke ( siehe Tweet )?

Einfacher Cache-Anbieter

  • [ ] Cache-Invalidierung (@acdlite) [#13337]
  • [ ] Abonnements (@acdlite) [#13337]
  • [ ] Entscheiden Sie sich für den tatsächlichen Namen

Code-Aufteilung

  • [x] Supportversprechen als Komponententyp
  • [x] (vielleicht) Open Source lazyLoadComponent ?

Renderer testen

  • [ ] Öffentliche APIs für flushAll , yield usw. fertigstellen

    • Der vorläufige Plan sieht vor, benutzerdefinierte Matcher für jedes der großen Testframeworks zu veröffentlichen, a la #13236.

Dokumente

  • [ ] Blogeintrag
  • [ ] React.Placeholder
  • [ ] einfacher-Cache-Anbieter
  • [ ] Unbenannte Code-Splitting-Bibliothek

Nachverfolgungen

Weicher Ablauf (https://github.com/facebook/react/issues/14248)

  • [ ] Implementieren Sie eine API für In-Place-Ladeindikatoren, die keine Vorfahren sind
  • [ ] Stellen Sie sicher, dass es eine Möglichkeit gibt, das Blinken des Inline-Spinners zu vermeiden, wenn er schnell genug ist

Streaming-Server-Renderer

  • [ ] Implementieren Sie einen Streaming-Server-Renderer wie den in @acdlites ZEIT-Talk
  • [ ] Teilweise Flüssigkeitszufuhr

Verwandte: Time Slicing Regenschirm (https://github.com/facebook/react/issues/13306)

React Core Team Umbrella

Hilfreichster Kommentar

@mschipperheyn

Dies ist ein mehrjähriges Projekt. Die ehrliche Antwort ist, dass es viel mehr Arbeit hervorgebracht hat, als wir dachten, als wir vor zwei Jahren damit begannen.

Aber die gute Nachricht ist, dass die fehlenden Teile klar sind und wir das Ende des Tunnels sehen, da wir es jetzt stark in der Produktion verwenden. Es ist nicht theoretisch – es gibt eine begrenzte Anzahl von Dingen, die wir abschließen müssen, bevor wir mit gutem Gewissen sagen können, dass es für eine breite Akzeptanz bereit ist.

Hier ist ein grober Zustand verschiedener Workstreams heute:

  • <Suspense> API zum Aufteilen von Code mit lazy . ( ausgeliefert in React 16.6)

    • Wie Sie vielleicht wissen, können Sie diesen bereits verwenden.

  • APIs für den gleichzeitigen Modus, z. B. createRoot und useTransition . ( verfügbar in experimental Versionen)

    • Kompatibilitätslösung für Flux-ähnliche Bibliotheken. ( in Bearbeitung @bvaughn , https://github.com/reactjs/rfcs/pull/147)

    • Ändern des Prioritätsmodells in ein vernünftigeres. ( in Bearbeitung @acdlite , https://github.com/facebook/react/pull/18612)

    • Lassen Sie nur den letzten ausstehenden Übergang zu Ende. ( in Bearbeitung @acdlite)

    • Offscreen-API ( in Bearbeitung @lunaruan)

    • Feuereffekte beim Ausblenden/Anzeigen von Inhalten für Suspense

    • Feuereffekte beim Ausblenden/Anzeigen von Inhalten für den Offscreen

    • Portal-Kinder bei Bedarf ein- und ausblenden

    • Abgleich mit den laufenden Standardisierungsarbeiten für die Terminplanung ( noch nicht begonnen )

    • Behebung wichtiger bekannter Fehler ( in Bearbeitung @gaearon und @acdlite)

    • Ereignissemantik ändern. ( in Bearbeitung @sebmarkbage @trueadm)

    • Delegieren Sie an Roots statt an das Dokument, um eine schrittweise Übernahme zu ermöglichen ( in Bearbeitung , @trueadm)

    • Flush diskrete Ereignisse in der Erfassungsphase.

    • Ziehen Sie in Betracht, die Standardpriorität von event zu erhalten, um mit imperativem Code besser zu spielen.

    • Finalisieren Sie andere API-Semantiken und -Standards. ( nicht gestartet )

    • Aktualisieren Sie die Eingaben und die Dokumentation.

  • Spannung beim Datenabruf

    • Low-Level-Unterstützung für die Signalisierung einer Komponente ist nicht bereit zum Rendern (technisch auch in Stable React

    • Der Server-Renderer löscht sofort Suspense-Fallbacks (in experimentellen Versionen verfügbar )

    • Eine Lösung für GraphQL-Anwendungsfälle (Relay Hooks, ausgeliefert ).

    • Eine Lösung für Nicht-GraphQL-Anwendungsfälle ( in Bearbeitung @sebmarkbage in Zusammenarbeit mit Next.js).

    • Eine Bundler-Integration für datengesteuerte Abhängigkeiten. ( in Bearbeitung )

    • Finalize Blocks API, einschließlich Kontext.

    • Eine generische Caching-Lösung. ( nicht gestartet )

    • Eine Art Router-Integration.

Es fühlt sich fast an wie "Es ist in Produktion bei Facebook, also sind wir fertig".

Ich kann mir vorstellen, wie es so aussehen könnte, auch wenn diese Lesart ein wenig demoralisierend ist. :-) Wir haben die letzten Monate ununterbrochen daran gearbeitet und viele der technischen Aspekte sind entweder fertig oder stehen kurz vor der Fertigstellung. Die meisten der verbleibenden Werke fallen in zwei Kategorien:

  • Behebung der Fehler, die wir in den ursprünglichen Designs entdeckt haben, bevor wir sie in einer stabilen Version festsetzen. Wenn wir das veröffentlichen würden, was wir jetzt haben, müssten wir in wenigen Monaten bedeutende Änderungen vornehmen. Das würde nur verwirren.

  • Ökosystemkompatibilität und gute Standardeinstellungen. Es hilft nichts, wenn wir etwas veröffentlichen, das heute niemand benutzen kann, weil es mit seinen Bibliotheken oder bestehenden Ansätzen nicht funktioniert. Der Großteil der Arbeit (zB Kompatibilität mit Flux-ähnlichen Bibliotheken über useMutableSource , Auswahl einer besseren Ereignissemantik, Versand einer empfohlenen Caching-Strategie) besteht darin, sicherzustellen, dass Sie tatsächlich in der Lage sind, das , was wir veröffentlicht haben, zu verwenden. Dies ist ein langer Schwanz.

Im Sinne von "kannst du heute verwenden"... Technisch gesehen kannst du all dies heute nutzen. Wir tun. Insbesondere verwenden wir Relay Hooks und Concurrent Mode. Wir haben noch erhebliche geplante Änderungen und bekannte Probleme, sodass der aktuelle Status nicht die Messlatte erreicht, die wir für eine breite Akzeptanz halten würden. Wenn es Ihnen nichts ausmacht , Fehler oder APIs direkt unter Ihren Händen zu ändern, können Sie die @experimental Releases natürlich genauso verwenden wie wir.

Ich würde nicht sagen, dass Facebook hier eine Sonderstellung einnimmt, wenn es darum geht, dass wir „fertig“ sind. Ganz im Gegenteil, wir sind noch nicht fertig – aber intern sind wir bereit, Abwanderungen zu tolerieren und auf einem fahrenden Zug aufzubauen, weil wir wissen, dass das, was wir bauen, solide ist. Ohne dieses schwere Dogfooding würde es mehrere Jahre dauern, die Mängel, die wir in sechs Monaten entdeckt haben, zu entdecken und neu zu gestalten.

Um es zusammenzufassen: Es gibt noch mehr zu tun.

Alle 83 Kommentare

Enthülle unstable_AsyncMode (vielleicht?)

Ist das nicht schon aufgedeckt ?

Ich meinte, unstable_ remove entfernen

Ich freue mich auf Open Source der unbenannten Code-Splitting-Bibliothek 💯

Was bedeutet es [Regenschirm]?🤔☂️

Dies bedeutet, dass es sich um eine Funktion handelt, die sich auf mehrere Projekte/Pakete/Tools auswirkt.

@ghoullier Ich vielen Dank!

Hey @acdlite , nur eine Frage, wie man sich am besten darauf vorbereitet. Nicht nach einer Zeitleiste fragen / erwarten, sondern sich fragen:

Erwarten Sie derzeit, dass diese Funktionen in React 16 aufgenommen und schrittweise übernommen werden können, wie die neue Context-API, die mit 16.3 gelandet ist?

Oder denkst du, dass es etwas sein wird, das React auf v17 pusht und mehr Arbeit erfordert, um es zu übernehmen?

Ich frage, weil ich an einer Roadmap arbeite, die sich mit so ziemlich allem auf Ihrer Liste stark überschneidet, und versuche herauszufinden, wie man damit am besten umgeht.

Haben Sie auch Tipps zur besten Vorbereitung (in Bezug auf heute geschriebenen Code, der mit diesen Verbesserungen von React zukunftskompatibel sein möchte) - Polyfills / Techniken / usw.?

(Entschuldigung, falls diese Fragen an anderer Stelle beantwortet wurden und ich sie übersehen habe)

Eine weitere Frage zu den Fragen von @JedWatson hinzufügen :

  • Wir brauchen/erwarten auch keinen Zeitplan für ein stabiles Release, aber wäre es möglich/nützlich, ein neues Prerelease zu bekommen? (AFAIK, die neueste Version ist 16.4.0-alpha.0911da3 vom Februar.)

Danke schön! ️

IMO, sie werden einen Blog-Beitrag wie zuvor bereitstellen, bevor er gelandet ist.

Und ich denke, Sie müssen nicht zu viel vorbereiten, da es keine bahnbrechenden Änderungen gibt (es gibt viele Funktionen, die möglicherweise anders erscheinen / im Widerspruch zu aktuellen Praktiken stehen, wie Redux-Fetch mit Spannung, aber es wird einen Codemod oder eine einfache Kapselung geben dafür hat fb 3W+ Komponenten). Und wenn Sie sich den Vortrag von @acdlite (über ssr-Spannung in der ZEIT) und @gaearon (über Client-Spannung in Island) ansehen, wissen Sie, dass Sie sich keine Sorgen machen müssen und es nicht invasiv ist.

Du kannst übrigens einfach im Repo nach dem Schlüssel 'Umbrella' suchen und du findest weitere Infos wie #8830 und #12152

AFAIK die neueste Version ist 16.4.0-alpha.0911da3 vom Februar.

IIRC, ist dies eine Fehlbedienung?

@JedWatson Dieser Kommentar hat mir geholfen zu verstehen, was ein Entwickler tun muss, um sicherzustellen, dass seine Anwendungen asynchron sicher sind .

Ich arbeite daran, das Suspense-Modul und neue APIs in Facebook einzuführen. Falls @acdlite mit etwas anderem beschäftigt ist, möchte ich einige meiner Erfahrungen zu unseren Erfahrungen auf Facebook teilen und einige Fragen von @JedWatson beantworten.

Erwarten Sie derzeit, dass diese Funktionen in React 16 aufgenommen und schrittweise übernommen werden können, wie die neue Context-API, die mit 16.3 gelandet ist?

Ich bin mir nicht sicher, ob es mit React 16 oder 17 kommen wird. Laut dem React-Team wird es wahrscheinlich vor Ende dieses Jahres veröffentlicht, was davon abhängt, wie gut es in Facebook läuft und wie die zugehörige API bereit ist oder nicht. Aber in Bezug auf den Code freue ich mich, sagen zu können, dass es einfach wäre, ihn zu übernehmen, da wir schon eine ganze Weile mit Facebook experimentieren. Die Suspense-Funktion funktioniert weiterhin für die vorhandene Codebasis. Aber mit zusätzlichen Änderungen (wie asynchronem Rendering) haben Sie mehr Bonus, den Ihnen die neue Funktion bietet.

Haben Sie Tipps zur optimalen Vorbereitung (in Bezug auf Code, der heute geschrieben wurde, der mit diesen Verbesserungen von React zukunftskompatibel sein möchte) - Polyfills / Techniken / usw.?

Ich würde sagen, die Migration ist eher inkrementell und progressiv. Wie @NE-SmallTown sagte, wollen wir keine Breaking Changes einführen. Das wäre auch mühsam auf Facebook auszurollen, weil wir eine so große Codebasis haben. Bisher verlief die Einführung jedoch reibungslos und erfordert keine zusätzlichen Änderungen.

@JedWatson

Erwarten Sie derzeit, dass diese Funktionen in React 16 aufgenommen und schrittweise übernommen werden können, wie die neue Context-API, die mit 16.3 gelandet ist?

Inkrementell. Immer inkrementell :) Sonst könnten wir das bei Facebook nicht versenden.

Folgendes erwarte ich:

| | Kunde | Serverseitiges Rendering |
|-----------------|-------------------------------------|-- --------------------------------------------------------|
| Spannung | Funktioniert überall* | Dieselben Einschränkungen wie beim vorhandenen Server-Renderer |
| Asynchrones Rendering | Melden Sie sich mit <AsyncMode> | Dieselben Einschränkungen wie beim vorhandenen Server-Renderer |

*Im Synchronisierungsmodus ist delayMs immer 0 . Platzhalter werden sofort angezeigt.

Suspense funktioniert ohne Änderungen an Ihren bestehenden Komponenten. An einem Punkt dachten wir, wir könnten <StrictMode> Kompatibilität benötigen, aber während unserer internen Tests haben wir herausgefunden, dass eine der besten Möglichkeiten zum Upgrade auf den strikten Modus die Verwendung von Suspense war. Huhn-Ei-Dilemma. Also haben wir einen Weg gefunden, es auch außerhalb des strikten Modus zum Laufen zu bringen.

Die Idee ist also, dass Benutzer mit der Migration zu Suspense beginnen, noch bevor sie bereit sind, zum asynchronen Rendering zu migrieren. Sobald ein Unterbaum fertig ist, können sie sich anmelden, indem sie <AsyncMode> .

Bei neuen Apps sieht die Geschichte jedoch anders aus: Gehen Sie standardmäßig asynchron. Wir werden eine neue Root-API (ein Ersatz für ReactDOM.render ) einführen, die nur asynchron ist.

Nach der ersten Veröffentlichung wird es eine unangenehme Zeit geben, in der viele Frameworks von Drittanbietern (Redux, Apollo, React Router ...) im asynchronen Modus möglicherweise nicht richtig funktionieren. Das könnte die Akzeptanz für eine Weile beeinträchtigen. Aber die Idee ist, dass die neuen Funktionen so überzeugend sein werden, dass es nicht lange dauern wird, bis sich Bibliotheken entweder anpassen oder durch eine async-kompatible Alternative ersetzt werden.

Haben Sie auch Tipps zur besten Vorbereitung (in Bezug auf heute geschriebenen Code, der mit diesen Verbesserungen von React zukunftskompatibel sein möchte) - Polyfills / Techniken / usw.?

Wickeln Sie alles in <StrictMode> und stellen Sie sicher, dass keine Warnungen angezeigt werden. Wir werden detailliertere Migrationsleitfäden haben, wenn wir uns der Veröffentlichung nähern.

Nach der ersten Veröffentlichung wird es eine unangenehme Zeit geben, in der viele Frameworks von Drittanbietern (Redux, Apollo, React Router ...) im asynchronen Modus möglicherweise nicht richtig funktionieren.

Apollo ist nicht umständlich - wir sind bereit! 🕺😳

Aber im Ernst, wir :heart: alles was mit React zu tun hat, also sicherzustellen, dass wir mit diesen Änderungen für die erste Veröffentlichung übereinstimmen, hat nicht nur hohe Priorität, sondern ist auch etwas, worauf wir uns sehr freuen! Vielen Dank für Ihre großartige Arbeit an diesem @acdlite!

Ich melde mich und sage, dass das Redux-Team an einem asynchronen Compat für React-Redux arbeitet.

Ich habe eine mögliche Roadmap unter https://github.com/reduxjs/react-redux/issues/950 erstellt . TL; DR:

  • React-Redux 5.1 wird hoffentlich ohne Warnungen mit <StrictMode> funktionieren (aktuelle PR: https://github.com/reduxjs/react-redux/pull/980 )
  • 6.0 wird intern neu geschrieben, um die neue Kontext-API zu verwenden, Ref-Weiterleitung und möglicherweise andere Änderungen hinzuzufügen, aber versuchen Sie, so viel wie möglich von der aktuellen öffentlichen API zu behalten (dh <Provider> und connect() ). Wir werden sehen, wie gut das mit asynchronem Rendering funktioniert, und den besten Weg nach vorne herausfinden. (Meine frühere Machbarkeitsstudie befindet sich unter https://github.com/reactjs/react-redux/pull/898 , aber wir werden sie wahrscheinlich basierend auf anderen Erkenntnissen aus der 5.1-Arbeit wiederholen.) Es ist wahrscheinlich, dass dieses Release würde mindestens React 16.5 erfordern, da neuer Kontext und wahrscheinlich auch die noch unveröffentlichte PR "Kontext aus Lebenszyklusmethoden lesen" gerade zusammengeführt werden musste.
  • Danach sind wir offen für Ideen für eine andere React-Redux-API (ja, ja, das beinhaltet möglicherweise Render-Requisiten, Leute).

Wir würden uns über mehr Augen auf unser WIP freuen, und hoffentlich können uns die Leute noch mehr Feedback und Diskussion darüber geben, wie sie Redux mit React Suspense und asynchronem Rendering verwenden, damit wir sicherstellen können, dass Anwendungsfälle richtig abgedeckt werden. Wir hoffen auch, weitere Gespräche mit dem React-Team darüber zu führen, mit welchen Einschränkungen wir arbeiten müssen, und es wäre hilfreich, wenn wir einige Beispiel-Apps erhalten könnten, die uns zeigen, welche Probleme wir für alle lösen müssen das funktioniert richtig.

Ich freue mich auf die Veröffentlichung von Async Rendering und Suspense

@acdlite Fragen Sie auch zu Spannung und asynchronem Rendering.
Meine Frage ist, sobald sie eingeführt wurden und man mit dem Schreiben von Apps mit dieser neuen Version von React beginnt: Bedeutet dies, dass sich die React-API und die Art und Weise, wie die Leute reagieren, auch ändern werden? (auch wenn sie nicht vorhaben, Suspense- und async-Rendering zu verwenden?)

Ich gehe davon aus, dass es

Ich nehme an, es kann schwieriger sein, Reaktionscode mit Spannung zu schreiben

Hatten Sie Gelegenheit, die zweite Hälfte meines Vortrags zu sehen? Ich würde eher das Gegenteil sagen – es ist viel weniger knifflig, Suspense zum Abrufen von Daten zu verwenden als alles andere (einschließlich Redux, Local State oder einer anderen Bibliothek).

@gaearon habe ich nicht. Ich habe eher theoretisch gesprochen. Stellen Sie sich vor, es gibt bereits eine Reihe von Leuten, die wissen, zu reagieren. Wenn die Leute die Funktion des asynchronen Renderings und der Spannung nicht benötigen, warum sie dann zwingen, "neue" Reaktionen zu lernen? Vor allem, wenn die "neue" Reaktion Trickser ist? Aber: Ich bin nicht gut informiert, daher kann ich mich beim "kniffligeren" Teil irren - ich teile nur einige meiner Gedanken :).

In gewisser Weise sage ich, wenn 10 % der Apps die Funktion von Suspense und asynchronem Rendering benötigen, warum zwingen Sie dann in diesen anderen 90 %-Fällen die Leute dazu, "neue" Reaktionen zu lernen? Aber auch hier könnte ich mich irren, da ich noch nicht viele Informationen über Suspence und asynchrones Rendering gesammelt habe.

Ich denke, es ist schwer, ein Gespräch zu führen, wenn Sie sich meine Demos noch nicht angesehen haben.

Um es klar zu sagen: es gibt kein "neues React", diese Features durchbrechen keine bestehenden Muster 🙂. Sie sind additiv. Sie müssen auch keinen völlig anderen Code schreiben, um diese Funktionen zu nutzen – obwohl einige von ihnen nur funktionieren, wenn Sie moderne Lebenszyklusmethoden verwenden .

Obwohl dies nicht direkt mit Ihrem Anliegen zu tun hat, stimme ich nicht zu, dass sie "kniffliger zu verwenden" sind. Ich denke, dass Suspense viel einfacher zu verwenden ist als jeder andere derzeit existierende Lademechanismus. Das ist der Grund, warum ich mich so darauf freue. Aber auch hier müssen Sie keine der neuen Funktionen verwenden, wenn Sie dies nicht möchten. Alte Muster funktionieren weiter.

Ich empfehle wirklich , meinen Vortrag zu sehen . Ich bin sicher, dies wird viel mehr Sinn machen, wenn Sie diese Funktionen in Aktion sehen.

@gaearon

Alle alten Muster funktionieren weiter.

Danke für das Feedback Dan. Ja, so dachte ich, ich nehme an, wenn die Leute diese Funktionen nicht brauchen, sollten sie in der Lage sein, so zu schreiben, wie sie es früher getan haben, bevor diese Funktionen hinzugefügt wurden.

viel Glück.

Hey Dan (@gaearon), ich bin nicht pingelig, möchte es aber herausfinden. Oben hast du gesagt:

Aber auch hier müssen Sie keine der neuen Funktionen verwenden, wenn Sie dies nicht möchten. Alte Muster funktionieren weiter.

Was würde darauf hindeuten, dass ich in neuem React genauso codieren kann wie in "altem" React, zB könnte ich die Lebenszyklusmethoden auf die gleiche Weise verwenden usw. richtig?

Doch hier , sagt bvaughn dass getDerivedStateFromProps (oder componentWillReceiveProps) oft für ein Update genannt werden könnte, damit seine Lösung nicht auf Daten im Innern zu holen.

Meine Frage ist also, schließlich können wir das neue React nicht genau so verwenden wie zuvor, oder? Da AFAIK in aktuellen react componentWillReceiveProps oft bekommt nicht für ein Update genannt, ist es nicht?

@giorgi-m: Ja, die Lebenszyklusmethoden ändern sich, aber der Punkt ist, dass Suspense selbst eine Opt-in-Funktion ist. Alle Ihre vorhandenen React-Rendering-Methoden und das Rendering-Verhalten von React funktionieren unverändert. _wenn_ Sie sich jedoch anmelden, indem Sie einem Teil Ihrer App ein <AsyncMode> Tag hinzufügen, _und_ Sie beginnen, den Ansatz von Suspense zu verwenden, um den Bedarf an asynchronen Daten anzugeben, _dann_ können Sie davon profitieren. Nichts davon passiert, wenn Sie dies nicht zu Ihrer Codebasis hinzufügen.

@giorgi-m componentDidUpdate sollte anstelle von componentWillReceiveProps oder getDerivedStateFromProps .

@markerikson Sie sagen also, dass das, was bvaughn hier sagte, dass _getDerivedStateFromProps_ viele Male für ein Update aufgerufen werden kann, nicht unbedingt der Fall ist, wenn ich das <AsyncMode/> nicht aktiviert habe?
(Entschuldigung, dass ich solche Fragen stelle, aber sie erscheinen mir von Zeit zu Zeit und ich habe keine Ressource gefunden, die alle abdeckt).

ps. bvaughn hat die Optionalität im verlinkten Thread auch nicht erwähnt, daher hat es meinen Verdacht erregt.

Sollte eine Methode zum Einreihen von asynchronen Updates (zB deferSetState() für Klassenkomponenten im Gegensatz zu Renderer-spezifischen unstable_deferredUpdates() ) zur Core-Checkliste hinzugefügt werden?

Nach meinem Verständnis werden alle Updates für Glasfasern in asynchronen mode asynchron sein, was theoretisch bedeutet, dass deferSetState() unnötig wäre. Die unstable-async/suspense Demo mischt jedoch ein synchrones Update und ein asynchrones Update, und ich bin mir nicht sicher, wie das im async Modus (für "universelle" Komponenten) erreicht werden kann.

Es steht in der Checkliste für den Zeitschlitz-Regenschirm.

Supportversprechen als Komponententyp

In Verbindung damit, wenn Sie:

const PromiseType = new Promise(() => {})
class A extends Component {
    componentDidMount() {}
    componentDidUpdate() {}
    render() {
        return <div><PromiseType></PromiseType></div>
    }
}

Gibt es Heuristiken, wann die Lebenszyklen componentDidMount und componentDidUpdate aufgerufen werden.

  1. Wenn alle Kinder (einschließlich des Versprechens) gelöst wurden, was in diesem Fall bedeutet, dass sie nicht angerufen werden, da das Versprechen nie gelöst wird?
  2. Wenn alle unmittelbaren Gastkinder gerendert wurden?

@thysultan : componentDidMount und componentDidUpdate werden in der Commit-Phase aufgerufen, wenn ein UI-Baum vollständig gerendert und auf das DOM angewendet wurde.

Basierend auf meinem Verständnis von Suspense denke ich, dass die Antwort darin besteht, dass die Instanz A nie wirklich gemountet würde. Wenn PromiseType _did_ aufgelöst wurde, aber einer seiner weiteren Nachkommen ebenfalls versuchte, auf ein Versprechen zu warten, das sich nie auflöst, würde es wieder nie mounten. Somit würden cDM und cDU in diesen Beispielen nie ausgeführt.

(Jemand kann mich gerne korrigieren, wenn meine Annahmen hier falsch sind :) )

Ja, componentDidMount oder componentDidUpdate nur in der Commit-Phase ausgeführt, die erst ausgeführt wird, nachdem der gesamte Baum aufgelöst wurde. Dieser Baum enthält möglicherweise einige Platzhalter, die Sie explizit dort platziert haben (je nachdem, ob etwas darin noch aussetzt, nachdem wir lange genug gewartet haben) - aber wenn Sie ein Kind explizit ohne Platzhalter rendern, können Sie nie in enden eine Situation, in der es "nicht bereit" ist.

Ich freue mich wirklich darauf, damit spielen zu können (habe sogar viel Quellcode durchgeblättert, nur um herauszufinden, dass Sie noch keine funktionierende Version davon im World Wide Web veröffentlicht haben).

Gibt es etwas, was wir tun können, um dies zu veröffentlichen? :D

Sie können vom Master kompilieren, wenn Sie spielen möchten. Siehe Anweisungen in fixtures/unstable-async/suspense

@gaearon Habe ich

EDIT, habe die Antwort gefunden: Für alle anderen, die eifrig nach der Verwendung von Suspense in SSR für universelle Apps suchen. Ich habe diesen Kommentar von Dan gefunden, der uns wissen lässt, dass dies vorerst nur auf der Clientseite ist. Dieser Kommentar weist jedoch auch auf https://www.youtube.com/watch?v=z-6JC0_cOns hin, in dem über die möglichen Auswirkungen auf SSR gesprochen wird.

Wir beginnen tatsächlich bald mit einigen Arbeiten im Zusammenhang mit dem SSR-Fall.

Stellen Sie sich dieses Szenario in einer asynchronen React-App vor, die auf einem Low-End-Mobilgerät ausgeführt wird:

  1. Es wird eine externe Anzeige geladen, die die gesamte CPU beansprucht (😓)
  2. Der Benutzer klickt auf einen Link und der Router löst ein neues Rendern aus
  3. React befindet sich im asynchronen Modus, also wartet es, bis Chrome/Safari ihm die Berechtigung zur Nutzung der CPU erteilt, aber die Anzeige wird noch 3 Sekunden lang geladen
  4. Der Benutzer denkt, die App funktioniert nicht

Dieses Problem könnte mit der gleichen <Placeholder> Technik, die für Suspense beschrieben wurde, vermieden werden, indem beispielsweise ein Spinner nach 1 Sekunde angezeigt wird.

Wurde dieses Szenario berücksichtigt? Funktioniert <Placeholder> für langsame asynchrone Renderings?

@luishranz Es gibt zwei Mechanismen, um dies zu verhindern:

  1. React hat mit jedem Update eine Frist. Aktualisierungen durch Klicks und andere Interaktionen wie diese sollten innerhalb von ~150 ms aktualisiert werden, es sei denn, Sie entscheiden sich ausdrücklich für eine längere Frist (z. B. für nicht wesentliche Aktualisierungen). React erzwingt also synchron das Spülen, wenn etwas den Thread in Beschlag nimmt.

  2. React verwendet requestIdleCallback nicht mehr, weil die Browser tatsächlich nicht aggressiv genug sind, um dies zu planen. Der genaue Planungsansatz kann sich im Laufe der Zeit ebenfalls ändern, aber das ist uns definitiv wichtig.

Vielen Dank für die schnelle Antwort Dan.

  1. React hat für jedes Update eine Frist

Genial. Gibt es bereits eine API, die wir testen könnten?

  1. React verwendet requestIdleCallback nicht mehr, weil die Browser tatsächlich nicht aggressiv genug sind, um dies zu planen.

Das haben wir auch ausprobiert. Manchmal kann es in einer überfüllten App mit externen Anzeigen und Einbettungen von Twitter oder YouTube mehrere Sekunden dauern, bis requestIdleCallback aufgerufen und das Rendering abgeschlossen ist. Also 👍 dazu.

Übrigens, für uns gibt es einen weiteren Anwendungsfall im Zusammenhang mit Ihrer ersten Antwort: Wir versuchen, Lazyloads mit zwei Offsets zu verwenden. Der erste löst einen asynchronen Rendering aus, der zweite löst einen synchronen Rendering aus, wenn der asynchrone Render noch nicht abgeschlossen ist. Etwas wie das:

  1. Der Benutzer scrollt nach unten und es ist bei 1200px ein schweres Element: zum Beispiel der nächste Beitrag eines Blogs.
  2. Der erste Offset löst ein asynchrones Rendering des nächsten Beitrags aus.
  3. Der Benutzer scrollt weiter nach unten und er ist bei 600px des nächsten Beitrags.
  4. Der zweite Offset löst aus: Wenn der asynchrone Post fertig ist (ComponentDidMount aufgerufen), passiert nichts, aber wenn nicht, wird ein Sync-Render des gesamten Posts ausgelöst.

Anstelle der Zeit möchten wir den Flush mit einem zweiten Trigger steuern. Macht das Sinn? Kann es möglich sein?

Gibt es bereits eine API, die wir testen könnten?

Ich bin mir nicht sicher, ob Sie auf Master meinen oder nicht (async-Modus ist in npm-Releases nicht offiziell verfügbar), aber die Ablaufzeit wird jedem Update automatisch zugewiesen. Bei Ereignissen wie Klicks sind es im Prod-Modus ~150 ms. Sie können es nicht festlegen, obwohl Sie sich mit einer speziellen instabilen API für ein verzögertes (längeres) Update entscheiden können.

Anstelle der Zeit möchten wir den Flush mit einem zweiten Trigger steuern. Macht das Sinn? Kann es möglich sein?

Ja, es ist möglich. Einen solchen Mechanismus habe ich hier beschrieben: https://github.com/oliviertassinari/react-swipeable-views/issues/453#issuecomment -417939459.

Ich bin mir nicht sicher, ob Sie auf Master meinen oder nicht (async-Modus ist in npm-Releases nicht offiziell verfügbar)

Ja, wir verwenden das npm-Paket mit <unstable_AsyncMode> , flushSync und unstable_deferredUpdates .

Bitte beginnen Sie mit der Veröffentlichung von Alpha-/Beta-Versionen mit diesen Änderungen an npm! 🙏

Ja, es ist möglich. Ich habe einen Mechanismus wie diesen hier beschrieben: oliviertassinari/react-swipeable-views#453 (Kommentar).

Brillant. Viel besser als unsere aktuelle Implementierung mit unstable_deferredUpdates :)

Ich kann es kaum erwarten, <div hidden> . Ihr macht einen tollen Job.

@luishranz Vorsicht, diese Dinger _sind_ instabil. Kann Fehler enthalten oder ziemlich ineffizient sein (zB eine entscheidende Optimierung – "Wiederaufnahme" – ist noch nicht implementiert). Wir entfernen auch unstable_deferredUpdates zugunsten des neuen schedule Moduls ( schedule.unstable_scheduleWork ).

Ja, wir nutzen es nur für einen kleinen Teil der App und testen intensiv aber bisher so gut :)

KANN OFFTOPIC SEIN:
requestIdleCallback wird nur 20 Mal pro Sekunde aufgerufen - Chrome auf meinem 6x2-Core-Linux-Rechner ist für die UI-Arbeit nicht wirklich nützlich.
requestAnimationFrame wird häufiger aufgerufen, aber spezifisch für die Aufgabe, die der Name vermuten lässt.

Aus diesem Grund verwenden wir requestIdleCallback .

Was benutzt ihr alle statt requestIdleCallback ?

Ach natürlich. Wie dumm von mir. Ich habe mich gefragt, welche Browser-API das Scheduler-Modul unter der Haube anstelle von requestIdleCallback . Ich hätte die Frage klarer stellen sollen. 😅

Hallo,

Als ich versuchte, Suspense zu verstehen, habe ich festgestellt, dass ich keine Ahnung habe, welcher Teil einer App tatsächlich "suspendiert" ist, wenn die Komponente Suspend wird 😳😱.

Im folgenden Beispiel würde ich erwarten, dass Title sofort sichtbar ist, Spinner nach 1000ms und UserData nach ~2000ms (da das "Laden" der Daten für diese Komponente 2000ms dauert).
Aber was ich sehe ist, dass Title erst nach 1000ms zusammen mit Spinner erscheint.

// longRunningOperation returns a promise that resolves after 2000ms
const UserResource = createResource(longRunningOperation);

function UserData() {
  const userData = UserResource.read(cache, "Lorem Ipsum");
  return <p>User Data: {userData}</p>;
}

function Spinner() {
  return <h1>Fallback Loading Spinner</h1>;
}

function Title() {
  return <h1>Hello World</h1>;
}

function App() {
  return (
    <React.Fragment>
      <Title />
      <Suspense maxDuration={1000} fallback={<Spinner />}>
        <UserData />
      </Suspense>
    </React.Fragment>
  );
}

unstable_createRoot(document.getElementById("mount")).render(<App />);

(Das vollständige Beispiel, das React 16.6.0-alpha.8af6728 verwendet, finden Sie hier auf Codesandbox )

Gibt es eine Möglichkeit, Title sofort sichtbar zu machen und nur den anderen Teil der Anwendung "auszusetzen"? Oder habe ich Suspense vielleicht komplett falsch verstanden? (Wenn es eine bessere Möglichkeit gibt, diese Art von Fragen zu stellen, lassen Sie es mich bitte wissen)

Danke!

Hallo @nilshartmann! Tolle Frage!

Gibt es eine Möglichkeit, den Titel sofort sichtbar zu machen und nur den anderen Teil der Anwendung zu "sperren"?

Wenn ich das richtig verstehe, müssen Sie React explizit anweisen, _nicht zu warten_, bevor Sie Title wie in diesem Beispiel in das DOM spülen, um Title sofort sichtbar zu machen und nur die anderen zu "suspendieren". Teil der Anwendung, indem Sie die Teile, von denen Sie erwarten, dass sie sofort gerendert werden, in ein <Suspense maxDuration={0}> .

Ich kann mir vorstellen, dass dies aufgrund einiger zugrunde liegender Scheduler-Mechaniken auf niedrigerer Ebene der Fall ist? Ich würde das auch gerne besser verstehen, aber das sollte Ihr Problem vorerst lösen.

Ich bin gespannt, was da wirklich los ist.

(Wenn es eine bessere Möglichkeit gibt, diese Art von Fragen zu stellen, lassen Sie es mich bitte wissen)

Ich bin mir nicht sicher, ob es das gibt. 😄 Mir scheint es ganz klar. Danke für die Frage!

@TejasQ In meinem Browser wird beim Laden Ihres Beispiels der Fallback-Spinner sofort

@TejasQ danke für deine Antwort, aber @karlhorky hat recht: jetzt taucht Spinner sofort auf.

Huch! Das habe ich vermisst. Ich habe es versucht. 😅Lass es mich noch einmal anschauen und melde mich wieder. Ich muss etwas übersehen haben. ️

~Update: Ich versuche es hier herauszufinden und wir können zusammenarbeiten, wenn jemand daran interessiert ist, es in Echtzeit zusammen zu machen.~

Zweites Update: @philipp-spiess und ich habe es mir angeschaut und bin echt ratlos. Ich verstehe es immer noch nicht. Zu diesem Zeitpunkt bin ich mir nicht sicher, ob es sich um einen Fehler handelt, da dies tatsächlich ein unstable_ und Alpha-Feature ist, oder ob es etwas ist, das ich einfach nicht sehe.

In jedem Fall habe ich das Gefühl, dass das Kernteam entweder hilfreiche Antworten hat oder Ihre Frage nutzen kann, um React noch besser / zugänglicher zu machen.

Mal sehen, was sie zu sagen haben. 😄 Danke für den Hinweis, @nilshartmann!

Wurde dies als Teil von React v16.6 veröffentlicht? Der Blogbeitrag zeigt Beispielcode mit Suspense:

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() (
  <Suspense fallback={<div>Loading...</div>}>
    <OtherComponent />
  </Suspense>
);

Wurde dies als Teil von React v16.6 veröffentlicht?

Nur der Anwendungsfall Lazy Loading und nur im Synchronisierungsmodus. Der Concurrent-Modus ist immer noch WIP.

@nilshartmann

Im folgenden Beispiel würde ich erwarten, dass Title sofort sichtbar ist, Spinner nach 1000 ms und UserData nach ~2000 ms (da das "Laden" der Daten für diese Komponente 2000 ms dauert).

Ich glaube, Sie sind etwas verwirrt darüber, was maxDuration tut. Es ist ein neues mentales Modell, aber wir hatten noch keine Zeit, dies zu dokumentieren. Es wird also noch eine Weile verwirrend sein, bis der Concurrent-Modus in einer stabilen Version ist.

Herzlichen Glückwunsch zur Ankündigung des Hooks-Vorschlags. Ich möchte etwas mit dem Team teilen. Vor einiger Zeit habe ich eine Komponente namens useAsync-Hook ist in

Jetzt ist meine Hauptsorge, wie sich dies in Suspense integrieren lässt. Zum größten Teil kann ich wahrscheinlich die Suspense-APIs von React Async verwenden und den Benutzern die vertraute und einfache React Async-API zur Verfügung stellen, während ich die Scheduling-Funktionen von Suspense kostenlos anbiete. Nach allem, was ich gesehen habe, denke ich wirklich, dass die React Async-API im Vergleich zu den abstrakteren Suspense-APIs sinnvoller und zugänglicher ist. Im Wesentlichen versucht React Async, eine konkretere API anzubieten, die für eine etwas kleinere Untergruppe von Anwendungsfällen funktioniert.

Ich war überrascht, von der React Cache-Bibliothek zu erfahren. Für React Async habe ich bewusst keinen Cache-Mechanismus eingebaut, sondern mich für Vanilla Promises entschieden. Darüber hinaus Caching hinzuzufügen ist ziemlich einfach.

Schließlich bin ich besorgt über den Zugriff auf Suspense-Funktionen über benutzerdefinierte Hooks. Spannung scheint stark von mehreren eingebauten Komponenten abhängig zu sein, was es unmöglich macht (glaube ich?), diese von einem Hook aus zu verwenden. Wird es Suspense-Hooks geben? Oder gibt es eine andere Möglichkeit, die beiden zu integrieren?

Hallo. Wie kann ich Code mit Suspense/Lazy testen?
Jetzt wirft renderer.create(...)toTree()
"toTree() weiß noch nicht, wie man Knoten mit tag=13 behandelt"

Warum die Requisiten maxDuration in Suspense nur im Concurrent Mode und nicht im Synchronisierungs- und gleichzeitigen Modus verwendet werden. Kann jemand helfen zu erklären?

(Im Moment) bedeutet es, wie lange es Concurrent Mode erlaubt ist, diesen Baum ausstehend zu lassen, bevor er zum Commit gezwungen wird – es steuert effektiv die Frist für das Time-Slicing, und im Sync-Modus gibt es kein Time-Slicing. Das Warten vor dem Festschreiben des Baums würde zwangsläufig dazu führen, dass das Festschreiben ... nicht synchronisiert wird.

Ich habe Suspense in einer internen Anwendung zum Abrufen von Daten verwendet und komme sehr schnell auf den Grund, warum es noch nicht zum Abrufen von Daten gedacht ist.

Schließlich soll es jedoch zum Abrufen von Daten verwendet werden. Da es unwahrscheinlich ist, dass sich die API mit Ausnahme des Cache-Providers signifikant ändern wird, wie soll Suspense funktionieren, wenn Sie die Daten ändern müssen, nachdem Sie sie abgerufen haben?

Als Beispiel hier ein wirklich schrecklicher Hook aus meiner Anwendung.

function useComponentList(id) {
  const incomingComponents = useSuspenseFetch(
    React.useCallback(() => getComponentAPI().listComponents(id), [id])
  )

  const map = React.useMemo(
    () =>
      Map(
        (incomingComponents || []).map(component => [component.id, component])
      ),
    [incomingComponents]
  )

  return useCacheValue(map)
}

Dieser Haken:

  1. Ruft Daten mit dem angegebenen Callback vom angegebenen Endpunkt ab
  2. Transformiert diese Daten in eine ImmutableJS Map - Da dies potenziell teuer ist, merke ich mir den Vorgang.
  3. Gibt die Map zurück, die in useCacheValue , was der besonders unangenehme Teil ist.

useCacheValue sieht so aus:

export default function useCacheValue(value) {
  const [state, setState] = React.useState(value)
  React.useEffect(() => {
    setState(value)
  }, [value])

  return [state, setState]
}

mit der Idee, dass es sich um einen Hook handelt, der auf value Änderungen reagiert (was anzeigt, dass die Daten erneut abgerufen wurden), aber es dem Benutzer ermöglicht, die Reaction-Apps-Darstellung dieses Zustands zu ändern. In gewisser Weise verhält es sich wie ein sehr schlechter Cache (daher der Name).

Ich habe Mühe zu sehen, wie dieses Muster in seinem aktuellen Zustand mit Redux gut funktioniert. Gab es irgendwelche Erkenntnisse darüber, wie dies aussehen könnte, wenn es von einem Programmierer geschrieben wurde, der nicht ich bin, und wenn die Spannung zum Abrufen von Daten "bereit" ist? So wie es aussieht, ist dies viel mühsamer als die alleinige Verwendung von Redux mit zwingenden Fetching-Flags.

Dies wird wahrscheinlich viel einfacher, sobald Redux seine eigenen Hooks hat, da die Hauptschwierigkeit beim Zusammenspielen der beiden darin besteht, dass Redux einen HOC mit einem Kontext verwendet, der nicht offengelegt werden soll, aber ich würde trotzdem gerne sehen, was der Offizielle Antwort ist :)

Suspense soll mit einem externen Cache arbeiten ( kein Hook, der vom Zustand gesteuert wird). Wir stellen eine Referenzimplementierung eines solchen Caches bereit, die für einfache Anwendungsfälle geeignet ist. Relay implementiert seinen eigenen Caching-Mechanismus. Alle anderen Tools (wie Apollo) können auch ihren eigenen Cache implementieren, der kompatibel ist und sich möglicherweise von diesen beiden Implementierungen inspirieren lässt.

Mutation/Invalidation ist nicht die einzige Frage, die Antworten braucht. Wir müssen auch darüber nachdenken, wann Spinner angezeigt werden sollen, gängige Muster wie „Inline-Anzeige“, die sich möglicherweise außerhalb des suspendierten Baums befinden, koordinierende Ladezustände (für Dinge, die in einer Top-Down-Reihenfolge entsperrt werden müssen oder so wie sie sind eintreffen ready), Streaming-Rendering von Listen, wie sich dies auf die partielle Flüssigkeitszufuhr auswirkt und so weiter. Wir arbeiten an diesen Dingen, aber es gibt noch keine „offizielle Empfehlung“. Wenn ja, erfahren Sie es aus dem Blog, in dem wir Updates ankündigen.

Als Randnotiz ist Suspense für das Abrufen von Daten ein ausreichend anderes mentales Modell als das, was die Leute vielleicht gewohnt sind. Ich denke, es ist nicht fair zu erwarten, dass es notwendigerweise so leistungsfähig ist, wenn es in sehr uneingeschränkte Mechanismen wie Redux integriert wird. Aber wir werden sehen. Es ist jetzt schwer, etwas zu sagen.

@gaearon Wenn Sie sagen: "Wir arbeiten an diesen Dingen", gibt es ein Problem, das ich abonnieren kann, oder finden diese Diskussionen privat statt?

Danke, @gaearon :)

@ntucker Wie immer können Sie sich die laufenden Aktivitäten als PRs ansehen. Zum Beispiel: https://github.com/facebook/react/pull/14717 , https://github.com/facebook/react/pull/14884 , https://github.com/facebook/react/pull/15061 , https://github.com/facebook/react/pull/15151 , https://github.com/facebook/react/pull/15272 , https://github.com/facebook/react/pull/15358 , https ://github.com/facebook/react/pull/15367 und so weiter. Wir versuchen, in jede PR einige beschreibende Informationen zu geben, und Sie können die Verhaltensänderungen aus Tests sehen. Die Dokumentationsleiste für Experimente ist aus mehreren Gründen niedrig.

Wir werden ausführlichere Erklärungen zum ausgewählten Modell veröffentlichen, sobald wir uns sicherer sind, dass es tatsächlich funktioniert. Ich glaube nicht, dass es weder für uns noch für die Community produktiv sein wird, wenn wir jedes Experiment akribisch im Detail beschreiben, während es passiert. Die meisten unserer ersten Experimente scheitern, und die Dokumentation und Erklärung jedes einzelnen von ihnen würde unsere Arbeit verlangsamen.

Noch schlimmer ist, dass dies oft dazu führt, dass Leute ein mentales Modell um etwas herum bauen, von dem wir später feststellen, dass es nicht auf die ursprünglich geplante Weise funktioniert. (So ​​wie es bei maxDuration passiert, das wir gerade entfernt haben.) Daher ziehen wir es vor, unausgegorene Ideen zu teilen, bis es Ihre Zeit und unsere Zeit gut nutzt. Dies entspricht auch der Entwicklung von React in der Vergangenheit. Wenn etwas wirklich fertig ist (sogar für eine theoretische Abfassung des mentalen Modells), werden wir unsere ganze Aufmerksamkeit darauf richten, es zu dokumentieren und zu erklären.

Als Randnotiz ist Suspense für das Abrufen von Daten ein ausreichend anderes mentales Modell als das, was die Leute vielleicht gewohnt sind. Ich denke, es ist nicht fair zu erwarten, dass es notwendigerweise so leistungsfähig ist, wenn es in sehr uneingeschränkte Mechanismen wie Redux integriert wird. Aber wir werden sehen. Es ist jetzt schwer, etwas zu sagen.

@gaearon , zum Glück

Die im vergangenen November angekündigte Roadmap (https://reactjs.org/blog/2018/11/27/react-16-roadmap.html) zeigte, dass die „gleichzeitige“ Version von Suspense für das zweite Quartal 2019 geplant ist Q3 2019. Gibt es ein Update, das wir definitiv nicht in Bezug auf Q3 oder vielleicht Q3 usw. erhalten können?

Dies war das neueste Roadmap-Update, das ich finden konnte: https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an -update-to-the-roadmap

Wir haben bereits im Oktober eine experimentelle Version bereitgestellt: https://reactjs.org/docs/concurrent-mode-intro.html. Dies ist der gleiche Build, den wir in der Produktion ausführen. Es gibt noch mehr zu tun (sowohl in Bezug auf das Optimieren der API als auch das Erstellen von APIs auf höherer Ebene), aber Sie können damit beginnen, wenn Sie möchten.

Spannung bringt mich um

@gaearon Ich verstehe, dass Sie es in der Produktion verwenden. Aber ich bin sehr zurückhaltend, "experimentellen" Code in der Produktion zu verwenden. Ihr seid euch nicht im Klaren über Roadmap, Status, Fortschritt, Timings usw. Ist das Alpha-, Beta-, RC-Qualität? Dieser Begriff "experimentell" sagt mir "nicht anfassen".

Wir alle setzen unser Geschäft auf diesen Code und ich bin sicher, wir sind alle genauso überfordert wie ihr. Ein bisschen Klarheit, ein Blog, ETWAS würde wirklich helfen. Es fühlt sich fast an wie "Es ist in Produktion bei Facebook, also sind wir fertig".

@mschipperheyn

Dies ist ein mehrjähriges Projekt. Die ehrliche Antwort ist, dass es viel mehr Arbeit hervorgebracht hat, als wir dachten, als wir vor zwei Jahren damit begannen.

Aber die gute Nachricht ist, dass die fehlenden Teile klar sind und wir das Ende des Tunnels sehen, da wir es jetzt stark in der Produktion verwenden. Es ist nicht theoretisch – es gibt eine begrenzte Anzahl von Dingen, die wir abschließen müssen, bevor wir mit gutem Gewissen sagen können, dass es für eine breite Akzeptanz bereit ist.

Hier ist ein grober Zustand verschiedener Workstreams heute:

  • <Suspense> API zum Aufteilen von Code mit lazy . ( ausgeliefert in React 16.6)

    • Wie Sie vielleicht wissen, können Sie diesen bereits verwenden.

  • APIs für den gleichzeitigen Modus, z. B. createRoot und useTransition . ( verfügbar in experimental Versionen)

    • Kompatibilitätslösung für Flux-ähnliche Bibliotheken. ( in Bearbeitung @bvaughn , https://github.com/reactjs/rfcs/pull/147)

    • Ändern des Prioritätsmodells in ein vernünftigeres. ( in Bearbeitung @acdlite , https://github.com/facebook/react/pull/18612)

    • Lassen Sie nur den letzten ausstehenden Übergang zu Ende. ( in Bearbeitung @acdlite)

    • Offscreen-API ( in Bearbeitung @lunaruan)

    • Feuereffekte beim Ausblenden/Anzeigen von Inhalten für Suspense

    • Feuereffekte beim Ausblenden/Anzeigen von Inhalten für den Offscreen

    • Portal-Kinder bei Bedarf ein- und ausblenden

    • Abgleich mit den laufenden Standardisierungsarbeiten für die Terminplanung ( noch nicht begonnen )

    • Behebung wichtiger bekannter Fehler ( in Bearbeitung @gaearon und @acdlite)

    • Ereignissemantik ändern. ( in Bearbeitung @sebmarkbage @trueadm)

    • Delegieren Sie an Roots statt an das Dokument, um eine schrittweise Übernahme zu ermöglichen ( in Bearbeitung , @trueadm)

    • Flush diskrete Ereignisse in der Erfassungsphase.

    • Ziehen Sie in Betracht, die Standardpriorität von event zu erhalten, um mit imperativem Code besser zu spielen.

    • Finalisieren Sie andere API-Semantiken und -Standards. ( nicht gestartet )

    • Aktualisieren Sie die Eingaben und die Dokumentation.

  • Spannung beim Datenabruf

    • Low-Level-Unterstützung für die Signalisierung einer Komponente ist nicht bereit zum Rendern (technisch auch in Stable React

    • Der Server-Renderer löscht sofort Suspense-Fallbacks (in experimentellen Versionen verfügbar )

    • Eine Lösung für GraphQL-Anwendungsfälle (Relay Hooks, ausgeliefert ).

    • Eine Lösung für Nicht-GraphQL-Anwendungsfälle ( in Bearbeitung @sebmarkbage in Zusammenarbeit mit Next.js).

    • Eine Bundler-Integration für datengesteuerte Abhängigkeiten. ( in Bearbeitung )

    • Finalize Blocks API, einschließlich Kontext.

    • Eine generische Caching-Lösung. ( nicht gestartet )

    • Eine Art Router-Integration.

Es fühlt sich fast an wie "Es ist in Produktion bei Facebook, also sind wir fertig".

Ich kann mir vorstellen, wie es so aussehen könnte, auch wenn diese Lesart ein wenig demoralisierend ist. :-) Wir haben die letzten Monate ununterbrochen daran gearbeitet und viele der technischen Aspekte sind entweder fertig oder stehen kurz vor der Fertigstellung. Die meisten der verbleibenden Werke fallen in zwei Kategorien:

  • Behebung der Fehler, die wir in den ursprünglichen Designs entdeckt haben, bevor wir sie in einer stabilen Version festsetzen. Wenn wir das veröffentlichen würden, was wir jetzt haben, müssten wir in wenigen Monaten bedeutende Änderungen vornehmen. Das würde nur verwirren.

  • Ökosystemkompatibilität und gute Standardeinstellungen. Es hilft nichts, wenn wir etwas veröffentlichen, das heute niemand benutzen kann, weil es mit seinen Bibliotheken oder bestehenden Ansätzen nicht funktioniert. Der Großteil der Arbeit (zB Kompatibilität mit Flux-ähnlichen Bibliotheken über useMutableSource , Auswahl einer besseren Ereignissemantik, Versand einer empfohlenen Caching-Strategie) besteht darin, sicherzustellen, dass Sie tatsächlich in der Lage sind, das , was wir veröffentlicht haben, zu verwenden. Dies ist ein langer Schwanz.

Im Sinne von "kannst du heute verwenden"... Technisch gesehen kannst du all dies heute nutzen. Wir tun. Insbesondere verwenden wir Relay Hooks und Concurrent Mode. Wir haben noch erhebliche geplante Änderungen und bekannte Probleme, sodass der aktuelle Status nicht die Messlatte erreicht, die wir für eine breite Akzeptanz halten würden. Wenn es Ihnen nichts ausmacht , Fehler oder APIs direkt unter Ihren Händen zu ändern, können Sie die @experimental Releases natürlich genauso verwenden wie wir.

Ich würde nicht sagen, dass Facebook hier eine Sonderstellung einnimmt, wenn es darum geht, dass wir „fertig“ sind. Ganz im Gegenteil, wir sind noch nicht fertig – aber intern sind wir bereit, Abwanderungen zu tolerieren und auf einem fahrenden Zug aufzubauen, weil wir wissen, dass das, was wir bauen, solide ist. Ohne dieses schwere Dogfooding würde es mehrere Jahre dauern, die Mängel, die wir in sechs Monaten entdeckt haben, zu entdecken und neu zu gestalten.

Um es zusammenzufassen: Es gibt noch mehr zu tun.

@gaearon Danke für dieses Update! Und ich entschuldige mich, wenn mein Ton falsch war. Ich gebe zu, ich war ein bisschen frustriert, als ich monatelang Twitter durchforstete und nichts fand. Dieser Aspekt Server renderer immediately flushes Suspense fallbacks (available in experimental releases) sieht aus wie etwas, für das ich Zeit investieren könnte, um dies mit Apollo Graphql für unsere Implementierung zu testen.

Ja, es sollte bereit sein, damit Bibliotheksautoren und neugierige Leute anfangen können, damit zu spielen. Bei den fehlenden Teilen geht es hauptsächlich darum, "glückliche Wege" bereitzustellen, aber die meisten Klempnerarbeiten sollten vorhanden sein.

Server-Renderer löscht sofort Suspense-Fallbacks (verfügbar in experimentellen Versionen)

Wo kann ich das nachlesen? Ich hatte gehofft, API-Referenz für den gleichzeitigen Modus (experimentell), aber kein Glück.

Wenn jemand eine Demo hat, die Next.js, Relay Hooks und Concurrent Mode (mit SSR) zusammenfügt, wäre das großartig. Ansonsten versuche ich vielleicht einfach mein Glück, wenn ich genügend Unterlagen finde.

@CrocoDillon

Es gibt keine zusätzlichen Dokumente zu SSR, aber das liegt hauptsächlich daran, dass es sich nur um ein neues Standardverhalten handelt.

Wenn Sie eine experimentelle Version haben, wird stattdessen jedes Mal, wenn eine Komponente auf dem Server angehalten wird, das nächstgelegene Suspense-Fallback geleert. Auf dem Client würden Sie dann createRoot(node, { hydrate: true }).render(<App />) .

Beachten Sie, dass dies bereits alle neuen Hydratationsfunktionen aktiviert. So werden beispielsweise Ihre Suspense-Grenzen an das vom Server generierte Fallback-HTML „angehängt“ und dann versucht, vom Client zu rendern.

Beachten Sie auch, dass Sie mit der Flüssigkeitszufuhr beginnen können, bevor Ihre gesamte App geladen wird. Wenn <App> geladen ist, können Sie hydratisieren. Solange Komponenten darunter anhalten, wenn ihr Code nicht bereit ist (ähnlich wie faul). Was React in diesem Fall tun würde, ist , den HTML-Inhalt des Servers zu behalten, aber die Suspense-Grenze daran „anzuhängen“. Wenn die untergeordneten Komponenten geladen werden, wird sie weiterhin hydratisiert. Die hydratisierten Teile würden zu interaktiven und wiederholten Ereignissen.

Sie können @devknoll wahrscheinlich nach den nächsten Integrationsversuchen/Beispielen fragen. Wahrscheinlich hat er welche.

Sie können den gleichzeitigen Modus in Next.js aktivieren, indem Sie react@experimental und react-dom@experimental installieren und Folgendes zu next.config.js hinzufügen

// next.config.js
module.exports = {
  experimental: {
    reactMode: 'concurrent'
  }
}

Hier ist die Next.js-Diskussion dazu: https://github.com/zeit/next.js/discussions/10645

Ist es möglich, auf Unterbrechungen beim Server-Rendering zu warten (z. B. für die Generierung statischer Sites)? Ich stimme zu, dass die Verwendung von Rückrufen eine gute Standardeinstellung ist, frage mich nur, ob sie überschreibbar ist?

Beachten Sie auch, dass Sie mit der Flüssigkeitszufuhr beginnen können, bevor Ihre gesamte App geladen wird. Wanngeladen hat, können Sie hydratisieren. Solange Komponenten darunter anhalten, wenn ihr Code nicht bereit ist (ähnlich wie faul). Was React in diesem Fall tun würde, ist, den HTML-Inhalt des Servers zu behalten, aber die Suspense-Grenze daran „anzuhängen“. Wenn die untergeordneten Komponenten geladen werden, wird sie weiterhin hydratisiert. Die hydratisierten Teile würden zu interaktiven und wiederholten Ereignissen.

@gaearon meinst du, dass du eine Komponente normal auf dem Server rendern kannst, aber React.lazy auf dem Client verwendest? Ermöglicht Ihnen, das vollständige Markup vom Server zurückzugeben, aber das Parsen und Rendern des Komponentencodes auf dem Client zu verzögern. Das vom Server gerenderte Markup fungiert hier als Suspense-Fallback?

@robrichard Ich habe es nicht speziell mit React.lazy versucht (wir verwenden einen anderen Wrapper bei FB und Next hat auch eine eigene Version), aber ich gehe davon aus, dass es so funktionieren würde. Es lohnt sich zu überprüfen :-) Mit gewissen Einschränkungen — zB wenn Sie seine Requisiten aktualisieren und oben kein Memo-Bailout vorhanden ist, oder wenn Sie den Kontext darüber aktualisieren, müssen wir es entfernen und den Fallback anzeigen, weil wir nicht wissen, was wir tun sollen damit.

@gaearon wie ist der aktuelle Stand der partiellen Flüssigkeitszufuhr? Ich weiß, dass #14717 zusammengeführt wurde, aber ich bezweifle, dass es in eine Veröffentlichung aufgenommen wurde?

Es ist seit langer Zeit in jeder @experimental Version aktiv, solange Sie die unstable_createRoot API verwenden.

@gaearon können Sie bitte erläutern, was Sie mit "datengesteuerten Abhängigkeiten" meinen?

@gaearon können Sie bitte erläutern, was Sie mit "datengesteuerten Abhängigkeiten" meinen?

Ja, sicher. Ich muss mich für die Kürze der obigen Liste entschuldigen – sie ist sehr komprimiert und viele davon sind bedeutende separate Teilprojekte (weshalb sie Zeit brauchen).

Lassen Sie mich einen Schritt zurücktreten und einen breiteren Kontext geben, bevor Sie Ihre spezifische Frage beantworten. Der breitere Kontext ist, dass der Aufbau einer wirklich guten Datenabruflösung wirklich, wirklich schwierig ist. Nicht nur im Sinne der Umsetzung, sondern im Sinne des Designs. Typischerweise müsste man einen Kompromiss zwischen Colocation (die Datenanforderungen nah am Verwendungsort der Daten halten) und Effizienz (wie früh beginnen wir mit dem Laden der Daten und können wir Netzwerkwasserfälle vermeiden) eingehen. Dies ist im kleinen Maßstab nicht so auffällig, aber mit zunehmender Anzahl von Komponenten müssen Sie sich wirklich zwischen großer Leistung und einfach zu schreibendem Code entscheiden. In vielen Fällen erhalten Sie leider keines von beiden – weshalb das Abrufen von Daten im Allgemeinen ein so heißes Thema ist.

Wir haben eine sehr hohe Messlatte für das, was ins "offizielle" React kommt. Um "Reacty" zu sein, muss es so gut komponieren wie normale React-Komponenten. Dies bedeutet, dass wir nicht in gutem Glauben eine Lösung empfehlen können, von der wir glauben, dass sie nicht auf Tausende von Komponenten skaliert werden kann. Wir können auch keine Lösung empfehlen, die Sie zwingt, Code auf komplizierte optimierte Weise zu schreiben, um die Leistung zu erhalten. Hier bei FB haben wir viele Lektionen vom Relay-Team gelernt. Wir wissen, dass nicht jeder GraphQL verwenden kann oder Relay verwenden möchte (es ist an sich nicht sehr beliebt und das Team hat es nicht für die externe Übernahme optimiert). Aber wir möchten sicherstellen, dass unsere Datenabruflösung für allgemeines React die hart erarbeiteten Lektionen von Relay

Ich möchte betonen, dass es hier nicht nur um große Apps geht. Die Probleme sind bei großen Apps am auffälligsten, aber auch kleine Apps, die eine Reihe von Komponenten von npm importieren, leiden unter einer Teilmenge dieser Ineffizienzen. Zum Beispiel, wenn zu viel clientseitiger Code gesendet und in einem Wasserfall geladen wird. Oder laden Sie zu viel im Voraus. Außerdem bleiben kleine Apps nicht für immer kleine Apps. Wir möchten eine Lösung, die für eine App jeder Größe hervorragend funktioniert, genau wie das React-Komponentenmodell unabhängig von der Komplexität Ihrer App auf die gleiche Weise funktioniert.

Nun zu Ihrer speziellen Frage. Relay verfügt über eine Funktion namens "datengesteuerte Abhängigkeiten". Eine Möglichkeit, darüber nachzudenken, ist eine Entwicklung des dynamischen import . Dynamisches import ist nicht immer effizient. Wenn Sie Code nur laden möchten, wenn eine Bedingung wahr ist (zB "ist der Benutzer eingeloggt" oder "hat der Benutzer ungelesene Nachrichten"), besteht Ihre einzige Möglichkeit darin, ihn träge auszulösen. Dies bedeutet jedoch, dass Sie das Abrufen (wie bei React.lazy ) nur dann "starten", wenn etwas verwendet wird. Das ist eigentlich zu spät. Wenn Sie beispielsweise mehrere Ebenen von Code-Split-Komponenten haben (oder Komponenten, die auf Daten warten), würde die innerste erst geladen, nachdem die darüber liegende geladen wurde. Dies ist ineffizient und ist ein Netzwerk-"Wasserfall". Mit "datengesteuerten Abhängigkeiten" von Relay können Sie die Module angeben, die Sie als Teil der Abfrage abrufen möchten. Dh "wenn eine Bedingung wahr ist, fügen Sie diesen Codeblock in die Datenantwort ein". Auf diese Weise können Sie alle Code-Split-Chunks, die Sie benötigen, so früh wie möglich laden. Sie müssen die Colocation nicht gegen Leistung eintauschen. Dies mag keine große Sache sein, aber es hat buchstäbliche Sekunden im Produktcode eingespart.

Auch hier setzen wir Relay nicht in React ein, und wir wollen die Leute nicht zwingen, GraphQL zu verwenden. Aber konzeptionell ist die Funktion selbst generisch, und eine gute Open-Source-Lösung dafür würde es den Leuten ermöglichen, viel mehr Code aufzuteilen als heute (und somit viel weniger Client-JS-Code ausliefern!). Diese generische Funktion wird nicht genannt „datengesteuerte Abhängigkeiten“ – das ist nur ein Relay-Name, auf den ich mich bezog. Diese Funktion wird Teil einer größeren empfohlenen Lösung sein, die kein GraphQL erfordert. Ich habe es nur mit diesem Namen in der Liste erwähnt, weil dies viel zu erklären war für einen einzigen Aufzählungspunkt.

Ich hoffe, das klärt es.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen