Envuelva un componente React controlado, para permitir que los componentes omitan pares específicos de Prop/Handler. Incontrolable le permite escribir componentes React, con un estado mínimo, y luego envuélvalos en un componente que administrará el estado para Prop/Handlers si están excluidos.
npm i -S uncontrollableSi está un poco inseguro sobre el por qué de este módulo lee primero la siguiente sección. Si solo desea ver algunos ejemplos del mundo real, consulte los widgets React que hacen un uso intensivo de esta estrategia.
import { uncontrollable } from 'uncontrollable' ;useUncontrolledProp(value, defaultValue, onChange) => [value, onChange] Un gancho reaccionado que se puede usar en lugar del componente de orden superior anterior. Devuelve un conjunto completo de props que son seguros para extenderse a un elemento infantil.
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 Un gancho reaccionado que se puede usar en lugar del componente de orden superior anterior. Devuelve un conjunto completo de props que son seguros para extenderse a un elemento infantil.
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 } / > ;
} ; Una de las fortalezas de React es su modelo de extensibilidad, habilitado por una práctica común de empujar el estado del componente lo más alto posible. Si bien es excelente para permitir que los componentes extremadamente flexibles y fáciles de razonar, esto puede producir una gran cantidad de componentes de calderas para alambre con cada uso. Para componentes simples (como una entrada), esto generalmente es una cuestión de vincular el valor del value de entrada a una propiedad de estado principal a través de su controlador onChange . Aquí hay un patrón extremadamente común:
render ( ) {
return (
< input type = 'text'
value = { this . state . value }
onChange = { e => this . setState ( { value : e . target . value } ) }
/ >
)
} Este patrón mueve la responsabilidad de administrar el value de la entrada a su padre e imita la data de datos "bidireccional". A veces, sin embargo, no hay necesidad de que el padre administre directamente el estado de la entrada. En ese caso, todo lo que queremos hacer es establecer el value inicial de la entrada y dejar que la entrada la administre a partir de entonces. React se ocupa de esto a través de entradas "no controladas", donde si no indica que desea controlar el estado de la entrada externamente a través de un accesorio value , solo hará el contador para usted.
Este es un gran patrón que podemos usar en nuestros propios componentes. A menudo es mejor construir que cada componente sea lo más apaciente posible, suponiendo que los padres querrán controlar todo lo que tenga sentido. Tome un componente desplegable simple como ejemplo
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 >
) ;
}
} ¿Observe cómo no rastreamos ningún estado en nuestro menú desplegable simple? Esto es excelente porque un consumidor de nuestro módulo tendrá toda la flexibilidad para decidir cuál debería ser el comportamiento del menú desplegable. Observe también nuestra API pública (PropTypes), consiste en un patrón común: una propiedad que queremos establecer ( value , open ) y un conjunto de manejadores que indican cuándo queremos que se establezcan ( onChange , onToggle ). Depende del componente principal cambiar el value y open accesorios en respuesta a los manejadores.
Si bien este patrón ofrece una excelente cantidad de flexibilidad para los consumidores, también requiere que escriban un montón de código de calderas que probablemente no cambiará mucho de uso a uso. Con toda probabilidad, siempre querrán open en respuesta a onToggle , y solo en casos raros querrán anular ese comportamiento. Aquí es donde entra el patrón controlado/no controlado.
Solo queremos manejar el caso Open/Ontoggle nosotros mismos si el consumidor no proporciona un accesorio open (lo que indica que quiere controlarlo). En lugar de complicar nuestro componente desplegable con toda esa lógica, oscureciendo la lógica comercial de nuestro menú desplegable, podemos agregarlo más tarde, tomando nuestro menú desplegable y envolviéndolo dentro de otro componente que lo maneja para nosotros.
uncontrollable le permite separar la lógica necesaria para crear entradas controladas/no controladas, lo que le permite concentrarse en crear una entrada completamente controlada y envolverla más tarde. Esto tiende a ser mucho más simple de razonar también.
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)! ¡Ahora no necesitamos preocuparnos por el Open Ontoggle! El componente devuelto se open para nosotros suponiendo que debería estar open a lo que devuelva onToggle . Si queremos preocuparnos por ello, podemos proporcionar accesorios open y onToggle y la entrada no controlada simplemente los pasará.
Lo anterior es un ejemplo artificial, pero le permite envolver componentes aún más complejos, dándole mucha flexibilidad en la API que puede ofrecer un consumidor de su componente. Para cada par de Prop/Handlers, también obtiene un PROPERPROPPROP del formulario "predeterminado [PropName]", así que value -> defaultValue y open -> defaultOpen , etc. React Widgets hace un uso pesado de esta estrategia, puede verlo en acción Aquí: https://github.com/jquense/react-widgets/blob/5d1b530cb094cdc72f577fe01abe4a02dd265400/src/multiselect.jsx#l521