Wickeln Sie eine kontrollierte React -Komponente ein, damit bestimmte Prop/Handler -Paare von den Komponentenverbrauchern weggelassen werden können. Mit unkontrollierbarem können Sie React -Komponenten mit minimalem Zustand schreiben und sie dann in eine Komponente einwickeln, die den Zustand für Prop/Handler verwaltet, wenn sie ausgeschlossen sind.
npm i -S uncontrollable
Wenn Sie sich über das Warum dieses Moduls etwas nicht sicher sind, lesen Sie zuerst den nächsten Abschnitt. Wenn Sie nur einige Beispiele in der Praxis sehen möchten, sehen Sie sich React-Widgets an, die diese Strategie stark nutzen.
import { uncontrollable } from 'uncontrollable' ;
useUncontrolledProp(value, defaultValue, onChange) => [value, onChange]
Ein React -Haken, der anstelle der Komponente der oben genannten Ordnung verwendet werden kann. Es gibt einen vollständigen Satz von props
zurück, die sich in einem Kinderelement sicher ausbreiten können.
import { useUncontrolledProp } from 'uncontrollable' ;
const UncontrolledCombobox = ( { value , defaultValue , onChange } ) => {
// filters out defaultValue, defaultOpen and returns controlled
// versions of onChange, and onToggle.
const [ controlledValue , onControlledChange ] = useUncontrolledProp (
value ,
defaultValue ,
onChange
) ;
return < Checkbox { ... controlledProps } / > ;
} ;
useUncontrolled(props, propsHandlerHash) => controlledProps
Ein React -Haken, der anstelle der Komponente der oben genannten Ordnung verwendet werden kann. Es gibt einen vollständigen Satz von props
zurück, die sich in einem Kinderelement sicher ausbreiten können.
import { useUncontrolled } from 'uncontrollable' ;
const UncontrolledCombobox = ( props ) => {
// filters out defaultValue, defaultOpen and returns controlled
// versions of onChange, and onToggle.
const controlledProps = useUncontrolled ( props , {
value : 'onChange' ,
open : 'onToggle' ,
} ) ;
return < Checkbox { ... controlledProps } / > ;
} ;
Eine der Stärken von React ist das Erweiterungsbarkeitsmodell, das durch eine gängige Praxis ermöglicht wird, den Komponentenzustand so hoch wie möglich nach oben zu schieben. Dies ist jedoch hervorragend, um extrem flexibel und leicht über Komponenten zu argumentieren zu können. Dies kann jedoch eine Menge Kesselplatten erzeugen, um die Komponenten bei jeder Verwendung zu verdrahten. Für einfache Komponenten (wie eine Eingabe) ist dies normalerweise eine Frage der Bindung des value
an eine übergeordnete Zustandseigenschaft über den onChange
-Handler. Hier ist ein extrem häufiges Muster:
render ( ) {
return (
< input type = 'text'
value = { this . state . value }
onChange = { e => this . setState ( { value : e . target . value } ) }
/ >
)
}
Dieses Muster verlagert die Verantwortung, den value
von der Eingabe in seine übergeordneten und nachahmischen "Zwei-Wege" -Datenbank zu verwalten. Manchmal ist jedoch nicht erforderlich, dass der Elternteil den Status der Eingabe direkt verwaltet. In diesem Fall möchten wir nur den value
der Eingabe festlegen und die Eingabe von da an verwalten lassen. React befasst sich damit durch "unkontrollierte" Eingänge. Wenn Sie nicht angeben, dass Sie den Status der Eingabe extern über eine value
steuern möchten, wird sie nur die Buchhaltung für Sie durchführen.
Dies ist ein großartiges Muster, das wir in unseren eigenen Komponenten verwenden können. Es ist oft am besten, jede Komponente so aufzubauen, dass sie so staatenlos wie möglich sind, vorausgesetzt, der Elternteil möchte alles steuern, was Sinn macht. Nehmen Sie als Beispiel eine einfache Dropdown -Komponente
class SimpleDropdown extends React . Component {
static propTypes = {
value : React . PropTypes . string ,
onChange : React . PropTypes . func ,
open : React . PropTypes . bool ,
onToggle : React . PropTypes . func ,
} ;
render ( ) {
return (
< div >
< input
value = { this . props . value }
onChange = { ( e ) => this . props . onChange ( e . target . value ) }
/ >
< button onClick = { ( e ) => this . props . onToggle ( ! this . props . open ) } >
open
< / button >
{ this . props . open && (
< ul className = "open" >
< li > option 1 < / li >
< li > option 2 < / li >
< / ul >
) }
< / div >
) ;
}
}
Beachten Sie, wie wir in unserem einfachen Dropdown keinen Zustand verfolgen? Dies ist großartig, da ein Verbraucher unseres Moduls die gesamte Flexibilität hat, zu entscheiden, wie das Verhalten der Dropdown aussehen sollte. Beachten Sie auch, dass unsere öffentliche API (ProTTypes), sie besteht aus gemeinsamem Muster: einer Eigenschaft, die wir festlegen möchten ( value
, open
) und eine Reihe von Handlern, die angeben, wann wir sie einstellen möchten ( onChange
, onToggle
). Es liegt an der übergeordneten Komponente, den value
zu ändern und Requisiten als Reaktion auf die Handler open
.
Während dieses Muster den Verbrauchern eine hervorragende Flexibilität bietet, müssen sie auch eine Reihe von Boilerplate -Code schreiben, die wahrscheinlich nicht viel von der Verwendung zur Verwendung ändert. Wahrscheinlich möchten sie immer open
als Reaktion auf onToggle
und nur in seltenen Fällen werden dieses Verhalten außer Kraft gesetzt. Hier kommt das kontrollierte/unkontrollierte Muster ins Spiel.
Wir möchten nur den Fall offen/ontoggle selbst bewältigen, wenn der Verbraucher keine open
Requisite bereitstellt (was darauf hinweist, dass er ihn steuern möchte). Anstatt unsere Dropdown -Komponente mit all dieser Logik zu komplizieren und die Geschäftslogik unserer Dropdown -Liste zu verschleiern, können wir sie später hinzufügen, indem wir unsere Dropdown- und Wickeln in eine andere Komponente einwickeln, die das für uns verarbeitet.
uncontrollable
können Sie die Logik trennen, die zum Erstellen von kontrollierten/unkontrollierten Eingängen erforderlich ist, sodass Sie sich darauf konzentrieren können, eine vollständig kontrollierte Eingabe zu erstellen und später zu wickeln. Dies ist auch viel einfacher zu argumentieren.
import { uncontrollable } from 'uncontrollable' ;
const UncontrollableDropdown = uncontrollable ( SimpleDropdown , {
value : 'onChange' ,
open : 'onToggle'
} )
< UncontrollableDropdown
value = { this . state . val } // we can still control these props if we want
onChange = { val => this . setState ( { val } ) }
defaultOpen = { true } / > // or just let the UncontrollableDropdown handle it
// and we just set an initial value (or leave it out completely)!
Jetzt müssen wir uns keine Sorgen um den offenen Ontoggle machen! Die zurückgegebene Komponente wird für uns open
verfolgen, indem sie davon ausgeht, dass sie nur für die zurückgegebenen onToggle
open
werden sollte. Wenn wir uns darüber Sorgen machen wollen , können wir einfach open
und onToggle
-Requisiten bereitstellen, und die unkontrollierte Eingabe passt sie einfach durch.
Das obige ist ein erfundenes Beispiel, aber es ermöglicht es Ihnen, noch komplexere Komponenten zu wickeln, und Ihnen viel Flexibilität in der API bietet, können Sie einem Verbraucher Ihrer Komponente anbieten. Für jedes open
/Handler defaultValue
erhalten Sie defaultOpen
einen Standardprop des Formulars "Standard [ value
]". Hier: https://github.com/jquense/react-widgets/blob/5d1b530cb094cdc72f577fe01abe4a02dd265400/src/multiselect.jsx#l521