Eae Reacteros, vamos aprender a usar algo fantástico que facilita muito quando o papo é "Estilização" e "React"?
Introdução
Quando eu iniciei no React Native, eu particularmente não gostava da forma de estilizar, pois estava acostumado com o jeito web, saca? Css e etc. Foi aí que encontrei essa fantástica alternativa: styled components.
Além de você estilizar usando praticamente css, ele facilita em muitas outras coisas como passagem de props para mudança de estilo e separação do estilo por componente. Enfim, mais um monte de opções. Sugiro que dê uma boa lida na documentação, pois, além de fácil é bem completa.
Um ponto importante a ser ressaltado é que essa lib não é só para React Native, ela serve para React.js também.
SPOILER: vamos usar o mesmo projeto de checkbox do artigo anterior. Se você perdeu, corre lá : https://dev.to/alanrmachado/criando-seu-proprio-componente-checkbox-no-react-native-3np6
Então, bora lá.
Dependências
Partindo do princípio de que iremos usar o mesmo projeto do artigo anterior, nossa única nova dependência é o styled-components. É simples de instalar, basta seguir a instruções do link a seguir : https://styled-components.com/docs/basics#installation
E finalmente, código.
Na mesma pasta do componente CheckBox, crie um arquivo chamado styles.js.
Eu costumo sempre ter uma pasta por componente, e nela, eu tenho dois arquivos. O index.js que é o componente em si, e o styles.js que é onde fica todo o style desse componente. Acredito que a nível organização, seja uma boa prática.
"Falou demais já, não é Alan???". Foi mal, Reacteros, vamos codar =).
Abra o arquivo styles.js e importe o styled-components, assim:
import styled from "styled-components/native"
"Alan, por que tem esse /native no final?". Lembra que eu disse que essa lib serve para o React.js também? Pois é, tá aí o divisor de águas. Se for usar em um projeto React.js importe sem o /native, beleza?
Lembram como era nosso componente? Não? o.O
Ok, era assim :
<View style={styles.WrapperCheckBox}>
<TouchableOpacity onPress={handleChange} style={[
styles.CheckBox,
{ borderColor: props.checkColor ? props.checkColor : '#fff' }
]}>
{
props.value ? <Icon name="check"
style={{
fontSize: 16,
color: props.iconColor ? props.iconColor : '#fff'
}}
/> : null
}
</TouchableOpacity>
<Text style={[styles.LabelCheck, props.labelStyle]}>
{props.label}
</Text>
</View>
Indo aos poucos, vamos pegar nosso primeiro elemento, o WrapperCheckBox, para começarmos a brincar.
Sabe o que é bacana do styled components? É que basicamente ele cria, como eu costumo dizer, micro componentes já com o estilo certo. Ou seja, você não precisa ter um código cheio de views com a propriedade style sendo preenchida por um objeto que você criou ali, aqui, acolá... Sei lá. A questão é que você pode trocar isso:
<View style={styles.WrapperCheckBox}>
</View>
Facilmente por isso:
<WrapperCheckBox>
</WrapperCheckBox>
Sacou o que há de mais lindo nisso? "Mas Alan, COOOMOOO?".
Eu explico. Mãos a massa:
Pegue a farinha de trigo... Ops, quer dizer, abra o arquivo styles e comece digitando o seguinte código:
export const WrapperCheckBox = styled.View`
`
Dois pontos importantes.
O primeiro, é que você está fazendo um estilo que será usado em outro arquivo, portanto, você precisa exportá-lo. Até aqui, ok?
Outro ponto é, esse "styled" é o mesmo que importamos logo a cima. É como se esse styled guardasse praticamente quase todos os componentes de design que podemos importar do react-native. Basta colocar um ponto e buscar o componente que queremos criar. Nesse caso, precisamos de uma View. Por isso do "styled.View". Se fosse um Text, faríamos "styled.Text". De boa, né?
Dentro das aspas é onde colocamos as propriedades css desse componente. Vamos fazer o mesmo estilo que antes fizemos usando o StyleSheet, mas agora como se fosse css. Vai ficar assim:
export const WrapperCheckBox = styled.View`
flex-direction : row;
align-items: center;
`
Lembre-se, estamos realmente escrevendo css, portanto, a sintaxe deve ser a mesma. Ou seja, o estilo não é um objeto, portanto, ao final de cada instrução se usa ponto e virgula (;) e não (,). Se o row estivesse envolvido em uma aspas, daria erro, pois no css isso não existe. Beleza? Tudo bem até aqui?
Agora vamos a parte emocionante, bora ajustar no arquivo principal do componente.
Primeiro, temos que importar esse WrapperCheckBox. Agora os importes do componente deve estar assim:
import React from 'react';
import PropTypes from "prop-types"
import Icon from "react-native-vector-icons/FontAwesome"
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { WrapperCheckBox } from "./styles" // Esse é o nosso "micro componente"
Agora é só substituir. Vai ficar assim:
<WrapperCheckBox>
<TouchableOpacity onPress={handleChange} style={[
styles.CheckBox,
{ borderColor: props.checkColor ? props.checkColor : '#fff' }
]}>
{
props.value ? <Icon name="check"
style={{
fontSize: 16,
color: props.iconColor ? props.iconColor : '#fff'
}}
/> : null
}
</TouchableOpacity>
<Text style={[styles.LabelCheck, props.labelStyle]}>
{props.label}
</Text>
</WrapperCheckBox>
Animal, né?
Conseguiu ver a vantagem de usar style components? Primeiro que você escreve css para estilizar, segundo que, olha só como fica mais organizado o código. Não temos mais uma View, com um style e etc. Agora temos um simples cara chamado "WrapperCheckBox" e só. O estilo dele está em outro arquivo, facilitando e muito a manutenção.
Continuando...
Agora que conseguimos montar nosso primeiro estilo usando o styled-components, vamos para o próximo cara que devemos mexer. Que é o TouchableOpacity! Sim, meus amigos reacteros, é ele.
Vamos seguir o mesmo procedimento. Vá até o arquivo styles e crie-o. Eu sei que você consegue. Vai lá. Te espero.
Show, você deve ter feito dessa forma, certo?
export const CheckButtom = styled.TouchableOpacity`
width: 25px;
height: 25px;
border-width: 1px;
justify-content: center;
align-items: center;
`
Parabéns, ficou top! É isso mesmo que tínhamos que fazer :)
Agora vamos importar. Vai ficar assim:
import React from 'react';
import PropTypes from "prop-types"
import Icon from "react-native-vector-icons/FontAwesome"
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { WrapperCheckBox, CheckButtom} from "./styles"
Agora é só substituir não é mesmo? Não.
"Ué, Alan. Por quê?". Analisando essa view, lááááá no componente, podemos ver que ela tem um ternário na propriedade style, que altera seu border-color dependendo do que vem na props, certo? Então, como fazemos isso com o styled component?
Bom, vejo duas formas.
A primeira é manter a propriedade style e deixar praticamente como antes. Aliás, não comentei até agora, mas você continua podendo fazer estilos inline, mesmo sendo um cara criado com styled-components. Então, ficaria assim:
<WrapperCheckBox>
<CheckButtom onPress={handleChange} style={{ borderColor: props.checkColor ? props.checkColor : '#fff' }}>
{
props.value ? <Icon name="check"
style={{
fontSize: 16,
color: props.iconColor ? props.iconColor : '#fff'
}}
/> : null
}
</CheckButtom>
<Text style={[styles.LabelCheck, props.labelStyle]}>
{props.label}
</Text>
</WrapperCheckBox>
Legal, né? Sim, mas tem uma opção mais legal ainda =)
Esses "micro componentes" podem receber props também, sabia? Pois é. Então, porque não mandamos essa props direto para o estilo e lá ele resolve essa questão da cor, heim? Faremos isso então. Corre lá pro arquivo styles e vamos preparar isso.
Antes de mais nada, você percebeu que há um template string na sintaxe de criação desse micro componente, não é mesmo? E como conseguimos inserir código javascript dentro dessa aspas? Simples, usando esse cara aqui ---> ${ código aqui }
Na prática, vamos mandar a props "checkColor" direto para esse micro componente lidar com a cor. Para isso, vamos deixa o estilo dessa forma:
export const CheckButtom = styled.TouchableOpacity`
width: 25px;
height: 25px;
border-width: 1px;
justify-content: center;
align-items: center;
border-color : ${({ checkColor }) => checkColor ? checkColor : '#fff'}
`
Ou seja, estou usando a desestruturação para pegar somente a propriedade checkColor e verifico, se ela existe, eu acrescento de forma dinâmica o valor do border-color, atribuindo a cor que veio via props. Caso contrário, a cor será branca.
Se você quer se aprofundar mais nas maneiras de passar props, atributos e etc, indico fortemente a documentação do styled-components, que é bem completa.
https://styled-components.com/docs
Veja que temos um ícone também, cuja o qual foi importado do "react-native-vector-icons/FontAwesome".
"Alan, o styled componente tem View, Text, TouchableOpacity e etc. Ele tem esse ícone que usamos também?". A resposta é não. "Mas então, como transformamos esse cara em um style-component?". É simples, meu caro. O style-components nos proporciona uma maneira de transformar qualquer desses carinhas em um styled component. Vamos agora aplicar isso para você entender melhor.
Vai lá no arquivo styles e importa esse ícone. Após isso, crie um styled component chamado IconCheck com as mesmas características de estilo.
Vamos também deixar preparado, assim como fizemos para o componente anterior, a cor dinâmica, baseado na props iconColor.
Não se assuste, mas o resultado final do estilo fica assim:
export const IconCheck = styled(Icon)`
font-size : 16px;
color : ${({ iconColor }) => iconColor ? iconColor : '#fff'};
`
Ou seja, perceba que eu passei o componente que o styled component não tem, dessa forma --> export const IconCheck = styled(Aqui vai o componente icon importado do "react-native-vector-icons/FontAwesome"). Simples, não é?
Agora vamos importar esse micro componente que acabamos de criar e substituir no nosso componente principal. Vai ficar assim:
<WrapperCheckBox>
<CheckButtom onPress={handleChange} checkColor={props.checkColor}>
{
props.value ? <IconCheck color={ props.iconColor} name="check"/> : null
}
</CheckButtom >
<Text style={[styles.LabelCheck, props.labelStyle]}>
{props.label}
</Text>
</WrapperCheckBox>
Bom, vamos para o último estilo a ser criado, a label.
No caso da label, nós não precisamos preparar no styled component para que receba uma props. "Mas Alan, a label recebe uma props chamada labelStyle". Lembra que eu disse que por mais que criamos um styled component, o mesmo ainda continua podendo receber styles inline? Pois bem, como essa props é realmente um objeto de estilo, basta mantermos a propriedade style recebendo essa props naturalmente.
Então, o estilo ficará assim:
export const LabelCheck = styled.Text`
color: #fff;
margin-left: 6px;
`
Agora vamos importar esse micro componente e fazer a substituição em nosso componente principal, que ficará assim:
<WrapperCheckBox>
<CheckButtom onPress={handleChange} checkColor={props.checkColor}>
{
props.value ? <IconCheck color={props.iconColor} name="check" /> : null
}
</CheckButtom>
<LabelCheck style={props.labelStyle}>
{props.label}
</LabelCheck>
</WrapperCheckBox>
Só para finalizar, veja como ficou meu arquivo styles:
import styled from "styled-components/native"
import Icon from "react-native-vector-icons/FontAwesome"
export const WrapperCheckBox = styled.View`
flex-direction : row;
align-items: center;
`
export const CheckButtom = styled.TouchableOpacity`
width: 25px;
height: 25px;
border-width: 1px;
justify-content: center;
align-items: center;
border-color : ${({ checkColor }) => checkColor ? checkColor : '#fff'};
`
export const IconCheck = styled(Icon)`
font-size : 16;
color : ${({ iconColor }) => iconColor ? iconColor : '#fff'};
`
export const LabelCheck = styled.Text`
color: #fff;
margin-left: 6px;
`
Finalizando
Agora que já terminamos, vamos apagar os imports desnecessários e o StyleSheet que criamos no post anterior.
Nosso componente ficará:
import React from 'react';
import PropTypes from "prop-types"
import { WrapperCheckBox, CheckButtom, IconCheck, LabelCheck } from "./styles"
export default function CheckBox(props) {
function handleChange() {
const { onChange } = props;
if (onChange) {
return onChange();
}
}
return (
<WrapperCheckBox>
<CheckButtom onPress={handleChange} checkColor={props.checkColor}>
{
props.value ? <IconCheck color={props.iconColor} name="check" /> : null
}
</CheckButtom>
<LabelCheck style={props.labelStyle}>
{props.label}
</LabelCheck>
</WrapperCheckBox>
);
}
CheckBox.propTypes = {
label: PropTypes.string,
labelStyle: PropTypes.object,
iconColor: PropTypes.string,
onChange: PropTypes.func,
value: PropTypes.boolean,
cehckColor: PropTypes.string
}
E é isso aí, Reacteros. Nos vemos no próximo post :)
Top comments (1)
Cara ficou bem legal e mais simples de estilizar, parabéns, no aguardo de novos artigos.