Enrole um componente de reação controlado, para permitir que pares específicos de suporte/manipulador sejam omitidos pelos consumidores de componentes. Incontrolável permite que você escreva componentes do React, com o mínimo de estado, e então os envolva em um componente que gerenciará o estado para suporte/manipuladores se forem excluídos.
npm i -S uncontrollable
Se você não tiver certeza do porquê deste módulo, leia a próxima seção primeiro. Se você deseja ver apenas alguns exemplos do mundo real, confira os widgets do React, o que faz uso pesado dessa estratégia.
import { uncontrollable } from 'uncontrollable' ;
useUncontrolledProp(value, defaultValue, onChange) => [value, onChange]
Um gancho de reação que pode ser usado no lugar do componente de ordem superior acima. Ele retorna um conjunto completo de props
que são seguros para se espalhar para um elemento filho.
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
Um gancho de reação que pode ser usado no lugar do componente de ordem superior acima. Ele retorna um conjunto completo de props
que são seguros para se espalhar para um elemento filho.
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 } / > ;
} ;
Um dos pontos fortes do React é o seu modelo de extensibilidade, ativado por uma prática comum de empurrar o estado do componente o mais alto possível a árvore. Embora seja ótimo para permitir que seja extremamente flexível e fácil de raciocinar sobre os componentes, isso pode produzir muito caldeira para conectar componentes a cada uso. Para componentes simples (como uma entrada), geralmente é uma questão de amarrar o suporte value
de entrada a uma propriedade do estado -mãe por meio de seu manipulador onChange
. Aqui está um padrão extremamente comum:
render ( ) {
return (
< input type = 'text'
value = { this . state . value }
onChange = { e => this . setState ( { value : e . target . value } ) }
/ >
)
}
Esse padrão move a responsabilidade de gerenciar o value
da entrada para seus pais e imita o banco de dados "bidirecional". Às vezes, no entanto, não há necessidade de o pai gerenciar diretamente o estado da entrada. Nesse caso, tudo o que queremos fazer é definir o value
inicial da entrada e permitir que a entrada o gerencie a partir de então. O React lida com isso por meio de entradas "não controladas", onde, se você não indicar que deseja controlar o estado da entrada externamente por meio de um suporte value
, ele fará a manutenção de livros para você.
Este é um ótimo padrão que podemos usar em nossos próprios componentes. Muitas vezes, é melhor construir cada componente para ser o mais apátrida possível, assumindo que o pai querer controlar tudo o que faz sentido. Pegue um componente suspenso simples como exemplo
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 como não rastreamos nenhum estado em nosso suspensão simples? Isso é ótimo porque um consumidor do nosso módulo terá toda a flexibilidade para decidir qual deve ser o comportamento do suspensão. Observe também nossa API pública (ApropTepes), consiste em padrão comum: uma propriedade que queremos definir ( value
, open
) e um conjunto de manipuladores que indicam quando queremos que eles sejam definidos ( onChange
, onToggle
). Cabe ao componente pai alterar o value
e open
adereços em resposta aos manipuladores.
Embora esse padrão ofereça uma excelente quantidade de flexibilidade para os consumidores, também exige que eles escrevam um monte de código de caldeira que provavelmente não mudarão muito do uso para usar. Com toda a probabilidade, eles sempre desejam open
em resposta a onToggle
, e somente em casos raros desejará substituir esse comportamento. É aqui que entra o padrão controlado/não controlado.
Queremos apenas lidar com o caso Open/Ontoggle se o consumidor não fornecer um suporte open
(indicando que eles desejam controlá -lo). Em vez de complicar nosso componente suspenso com toda essa lógica, obscurecendo a lógica de negócios do nosso menu suspenso, podemos adicioná -lo mais tarde, levando nosso menu suspenso e envolvendo -o dentro de outro componente que lida com isso para nós.
uncontrollable
permite separar a lógica necessária para criar entradas controladas/não controladas, permitindo que você se concentre na criação de uma entrada completamente controlada e envolvendo -a mais tarde. Isso tende a ser muito mais simples de raciocinar também.
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)!
Agora não precisamos nos preocupar com o ontoggle aberto! O componente retornado open
para nós, assumindo que ele deve apenas se open
para qualquer retorno onToggle
. Se queremos nos preocupar com isso, podemos apenas fornecer adereços open
e onToggle
e a entrada não controlada apenas passará por eles.
O exposto acima é um exemplo artificial, mas permite que você envolva componentes ainda mais complexos, oferecendo muita flexibilidade na API, você pode oferecer um consumidor do seu componente. Para todos os pares de suporte/manipuladores, você também recebe um padrão do formulário "padrão [propname]" SO value
-> defaultValue
e open
-> defaultOpen
, etc. Os widgets react fazem uso pesado dessa estratégia, você pode vê -lo em ação Aqui: https://github.com/jquense/react-widgets/blob/5d1b530cb094cdc72f577fe01abe4a02dd265400/src/multisElect.jsx#l521