React: Klonen des untergeordneten Kontexts Verbraucher erzeugt verwirrende Warnungen und Fehler

Erstellt am 25. Apr. 2018  ·  4Kommentare  ·  Quelle: facebook/react

Möchten Sie eine Funktion anfordern oder einen Fehler melden?
Dies ist ein Fehler oder zumindest eine Anfrage nach genaueren Warnungen und Fehlermeldungen.

Wie ist das aktuelle Verhalten?

Ich habe Kinder geklont, um einige Eigenschaften hinzuzufügen, und ich habe übersehen, dass der Kontext-Consumer-Teilbaum nicht geklont werden sollte ...

import React from 'react';
import {render} from 'react-dom';

const { Provider, Consumer} = React.createContext();

const Comp = ({children})=> <Provider>{cloneKids(children)}</Provider>;

const cloneKids=(children)=>React.Children.map(children, child =>
                           React.cloneElement(child, child.props,
                                  child.props.children&&
                                  cloneKids(child.props.children)));
render(
    <Comp><Consumer>{console.log}</Consumer></Comp>,
    document.getElementById('root')
);

Der Code erzeugt die mit # 12241 eingeführte Warnung und den Fehler

Warnung: Ein Kontextkonsument wurde mit mehreren untergeordneten Elementen oder einem untergeordneten Element gerendert, das keine Funktion ist. Ein Kontextverbraucher erwartet ein einzelnes Kind, das eine Funktion ist. Wenn Sie eine Funktion übergeben haben, stellen Sie sicher, dass keine nachgestellten oder führenden Leerzeichen um sie herum vorhanden sind.

und (noch verwirrender)

TypeError: Rendern ist keine Funktion

Was ist das erwartete Verhalten?

Vielleicht sollte React.cloneElement nicht versuchen, Funktionen zu klonen? Was auch immer es tut, das Ergebnis ist keine Funktion.

Der Warnungsteil "Ein Kind, das keine Funktion ist" sollte von den anderen Warnungen getrennt werden. Es können nicht mehrere Kinder und ein Kind gleichzeitig eine Funktion sein, sodass eine genauere Warnung ausgegeben werden kann.

Welche Versionen von React und welcher Browser / welches Betriebssystem sind von diesem Problem betroffen?

Getestet mit Reagieren 16.3.0 in Stackblitz / Chrome 65 und Reagieren 16.3.2 in Chrome 65 und Firefox 59

Question

Hilfreichster Kommentar

Das Problem liegt nicht bei cloneElement (es gibt keine spezielle Logik für den Kontext), sondern darin, dass Sie props.children (was in diesem Fall eine Funktion ist) an Children.map() (was keine Funktionen erwartet). Children.map funktioniert nur mit regulären React-Knoten.

Vielleicht könnte Children.map eine Warnung anzeigen, wenn es auf etwas stößt, das kein React-Knoten ist.

In beiden Fällen klingt es so, als würden Sie versuchen, etwas zu tun, für das React nicht entwickelt wurde. Warum brauchst du das?

Alle 4 Kommentare

Das Problem liegt nicht bei cloneElement (es gibt keine spezielle Logik für den Kontext), sondern darin, dass Sie props.children (was in diesem Fall eine Funktion ist) an Children.map() (was keine Funktionen erwartet). Children.map funktioniert nur mit regulären React-Knoten.

Vielleicht könnte Children.map eine Warnung anzeigen, wenn es auf etwas stößt, das kein React-Knoten ist.

In beiden Fällen klingt es so, als würden Sie versuchen, etwas zu tun, für das React nicht entwickelt wurde. Warum brauchst du das?

Vielen Dank!

Ich verzögere die Bewertung einiger untergeordneter Eigenschaften, bis die Eltern bereit sind, den Kontext für ihre Bewertung bereitzustellen. Beispielsweise:

<Parent ><Child prefix-prop="string expression"></Parent>
(Die Ausdruckssprache ist kein Javascript und wird aus der Ferne ausgewertet. Ich kontrolliere Child nicht und es kann eine beliebige Anzahl von Kindern geben.)

Das Kind wird innerlich so etwas wie:

<Child prop={evaluate("string expression")} />

Um dies zu erreichen, besucht der Elternteil die untergeordneten Elemente und wandelt die Eigenschaft "prefix-prop", die den Ausdruck enthält, in die Eigenschaft "prop" um, die den Ausdruckswert enthält. Das Klonen ist der einzige Ansatz, mit dem ich die Komponenteneigenschaften ändern konnte. Natürlich sollten Verbraucher nicht geklont werden, da gibt es keine Eigenschaften, die geändert werden könnten.

Ich weiß, dass ich Funktion als Kind verwenden oder Funktionen oder ähnliches rendern sollte (um die Auswertung zu verzögern), aber ich entwerfe eine Prototyping-Bibliothek und meine Benutzer (die aus HTML und JSP stammen und häufig Anfänger sind, die über HTML und die Ausdruckssprache hinausgehen). wird diese Notation höchstwahrscheinlich nicht zu schätzen wissen:

<Parent>{ context=> <Child prop={context.evaluate(x)} />}</Parent>

(Außerdem werden sie durch # 12689 verwirrt, wenn sie kurz vor der Funktion ein Leerzeichen vergessen.)

und sie werden diese Form auch nicht schnell verstehen:
<Parent display={ context=> <Child prop={context.evaluate(x)} />} />

Kontextkonsumenten verwenden auch die Funktion "Kind", sodass sie das gleiche Problem haben.

Dies ist eine sehr frühe Arbeit, daher denke ich immer noch über Optionen nach, aber ich möchte irgendwie zu einer sauberen Eltern-Kind-Notation wie im ersten Zitat gelangen. Wahrscheinlich sollte ich ein Babel-Plugin schreiben, das die "saubere" Notation in eine funktionale umwandelt.

Aber vielleicht fehlt mir etwas, also würde ich mich über jede Eingabe freuen. Ich möchte wirklich, dass meine Benutzer JSP verlassen und React übernehmen, aber wenn die Notation zu kryptisch ist, wird dies nicht passieren ...

Eine andere Idee, mit der ich spiele, ist ein funktionaler Elternteil, der wahrscheinlich eine Komponente (eine Art HOC) zurückgibt.

({context})=>
context.parent("context expression",
     context2=><Child prop={context2.evaluate("sub-expression")} context={context2} />)

wo Child wieder context.parent () -Aufrufe enthalten kann, und so weiter.

Natürlich könnte parent () einen Kontext-Consumer in render () der zurückgegebenen Komponente verwenden, sodass die Kontext-Requisite gelöscht werden kann:

()=>
parent("context expression",
     context2=><Child prop={context2.evaluate("sub-expression")} />)

_Das Problem hierbei ist, dass parent () als Komponente auf den React-Kontext zugreifen kann, evalu () jedoch (meines Wissens) nicht auf den React-Kontext zugreifen kann, es sei denn, es gibt eine Komponente zurück_

Dies ist nicht möglich, wenn Sie tatsächlich versuchen, eine Eigenschaft festzulegen.

Daher halte ich den

React.getContext(Consumer, data=> ...)

Wenn ich mich recht erinnere, habe ich versucht, Consumer.render () manuell über das Testframework aufzurufen, aber ich habe nichts Sinnvolles bekommen.

PS: Die erste Notation oben mag kryptisch erscheinen, ist aber mit der aktuellen JSP-Form ziemlich vertraut, sodass ich denke, dass ich sie an die Benutzer verkaufen kann :)

<context:parent ctx="context-expression">
   HTML...<context:evaluate expr="sub-expression" />...HTML
</context:parent>

Zu schließen, da dies nicht oft vorkommt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen