Seu editor irá agradecer!

Substituindo React.PropTypes por Flow

Há alguns meses atrás no Product Hunt, nós decidimos mudar as declarações de React.PropTypes por Flow. De início, nós começamos usando Flow apenas para definições de funções, só depois, começamos a substituir os valores no objeto propType.

E qual foi o motivo dessa mudança? Vamos usar um exemplo, nós temos o componente UserImage, com dois possíveis uso:

<UserImage user={user} width={50} height={30} />  
<UserImage user={user} variant="small" />

Sua declaração é mais o menos a seguinte:

const UserShape = {  
id: React.PropTypes.number.isRequired,
name: React.PropTypes.name.isRequired,
};
class UserImage extends React.Component {  
static propTypes = {
user: React.PropTypes.shape(UserShape).isRequired,
width: React.PropTypes.number,
height: React.PropTypes.number,
variant: React.PropTypes.oneOf(['big', 'medium', 'small')
};
render() { /* ... */ }
}

Existem alguns problemas com essa declaração:

  • UserShape só poder ser usado com outro componente React
  • propTypes retorna mensagens em tempo de execução (console do navegador)
  • width e height devem ser passados ao mesmo tempo, não um ou outro, sempre os dois, mas nós não podemos forçar isso no exemplo acima
  • É possível passar as três propriedades ao mesmo tempo width, height e variant

Vamos ver como Flow resolve esses problemas:

type User = {  
id: number,
name: string,
};
class UserImage extends React.Component {  
props: {
user: User,
width: number,
height: number,
} | {
user: User,
variant: 'big' | 'medium' | 'small',
};
render() { /* ... */ }
}
  • User é um tipo genérico (pode ser usado em qualquer função javascript)
  • Os tipos do Flow são usados apenas durante o processo de build (erros e mensagens acontecem aqui, antes da execução)

E acreditem, o mais maneiro:

  • <UserImage user={user} width=”10" />, irá quebrar o build 😎

Infelizmente, o exemplo seguinte ainda é possível:

<UserImage user={user} width={50} height={30} variant="small" />

Quando estivermos usando a propriedade variant, nós não queremos habilitar a possibilidade de passar width e height (e vice-versa).

Para resolver esse problema, podemos usar:

props: {
user: User,
width: number,
height: number,
// esperamos que "variant" não seja passada
variant?: void,
} | {
user: User,
variant: 'big' | 'medium' | 'small',
// "width" e "height" não devem ser permitidos
width?: void,
height?: void,
};

É meio feio, mas funciona do jeito que esperamos:

Para mais informações, você pode verificar a documentação do Flow.

obs: Gabriele Petronella e Vjeux me disseram no twitter que você pode usar $Exact ou {| |}:

props: 
{| user: User, width: number, height: number |} |
{| user: User, variant: 'big' | 'medium' | 'small' |};

Obrigado por ter lido até aqui, se você gostou do post, manda um 💚 e compartilha no Twitter! Valeu! 🙏🏼


Créditos