React Native - Estilização

A grande vantagem que o React native nos traz, é tornar único o código tanto para Android, quanto para IOS. Não só pensando nos dispositivos móveis, graças ao React, o código pode ser utilizado no desenvolvimento web. Mas quando chegamos na parte de estilização, podemos ter que nos acostumar e perceber que nessa parte a diferença do que estamos acostumados a ver no desenvolvimento web, é maior que o esperado.

Cascading Style Sheets (CSS)

A princípio mexer com estilo no React native, parece ser bem simples. Podemos ver as regras de CSS e que diferente da web, onde as as mesmas são escritas em kebab-case, utilizaremos a sintaxe com CamelCase.

O React Native utiliza o mecanismo de layout de Yoga, que implementa as especificações do flexbox e empresta nomes de regras CSS. Ex:

1
2
3
4
.text {
font-family: Arial;
font-size: 12px;
}

Que ficaria assim no React native:

1
2
3
4
5
6
const styles = StyleSheet.create({
text: {
fontFamily: "Arial",
fontSize: 12,
}
});

Isso faz com que a escrita do estilo seja muito familiar. Mas depois fica claro que o estilo no React Native é muito diferente do estilo na web. Nomes de regras e flexbox são as únicas coisas que o CSS e o estilo no React Native tem em comum.

Escopo por componente

No navegador, o CSS tem o escopo a nível da página. Para uma aplicação web de uma única página, isso significa que cada folha de estilo afeta a aplicação inteira. As regras de estilos individuais são aplicadas aos elementos no DOM, sendo definidos dentro dos blocos dos seletores. Existem muitas maneiras diferentes de selecionar os elementos DOM.

Com o React Native, os estilos não tem efeito em seu aplicação, a menos que você os passe especificamente aos seus componentes. Não existe um conceito de seletor porque os componentes e os estilos estão bem acoplados. Isso significa que você pode usar o mesmo nome para estilos em várias folhas de estilo sem causar efeitos colaterais:

1
2
3
4
5
6
7
8
9
10
11
12
const headerStyles = StyleSheet.create({
container: {
backgroundColor: 'red'
}
});
const footerStyles = StyleSheet.create({
container: {
backgroundColor: 'red'
}
});
<Header style={headerStyles.container} />
<Footer style={footerStyles.container} />

Herança

Os estilos não são herdados por padrão. Na web, os elementos DOM herdam alguns dos estilos dos pais por padrão. Estes são principalmente estilos relacionados a texto, e isso significa que você pode fazer:

1
2
3
4
5
6
7
8
9
10
11
12
<style>
.container {
font-family: Arial;
font-size: 12px;
}
</style>
<div class="container">
<h1>Title</h1>
<div>
<p>Test with <strong>text</strong></p>
</div>
</div>

Que é equivalente a:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const styles = StyleSheet.create({
container: {
fontFamily: 'Arial',
fontSize: 12,
},
bold: {
fontWeight: '700',
}
});
<View>
<Text style={styles.container}>Title</Text>
<View>
<Text style={styles.container}>Test with <Text style={styles.bold}>text</Text></Text>
</View>
</View>

Os componentes podem para passar propriedades de estilo para os componentes filho. É o caso do <Text /> do React Native. Um componente <Text /> que é filho de outro componente <Text />, herdará seus estilos:

1
2
3
4
<Text style={styles.text}>
Text
<Text style={{fontWeight: bold}}>Text</Text>
</Text>

O compartilhamento de estilos de texto com <Text /> tem uso limitado, pois <Text /> não permite que a maioria dos outros componentes React Native sejam seus filhos.

Lógica no estilo

O CSS é muito limitado na sua capacidade de calcular valores. Existem algumas funções que você pode usar, como calc() e as variáveis CSS são suportadas em navegadores modernos. Além disso, a lógica para calcular estilos dinamicamente precisa ocorrer em outros lugares, sendo compilado com pré-processadores (como SASS).

No React Native, os estilos são definidos em JavaScript. Tendo uma linguagem de programação nos dá uma série de possibilidades.

Assim, temos novos padrões de estilo. Esse é um repositório que vale a pena ver.

Style e StyleSheet

Os estilos só podem ser transmitidos diretamente para um componente, da mesma forma que você passaria estilos para elementos DOM através do atributo style:

1
<p style="color: blue;">text</p>

Achou que iria se livrar do estilo inline? XD

A documentação do React native nos informar mais sobre o style.

O que pode ser novo para você é o StyleSheet, que cria uma folha de estilo a partir de um objeto de estilo, tornando possível se referir a ele por ID ao invés de criar um novo objeto de estilo sempre.

Gerenciando estilos

Pra mim, essa é a parte mais critica. Antes de recorrer a módulos de terceiros, uma escolha minha e um conselho é explorar as possibilidades ao utilizar o React native, principalmente se a ideia é ir para a linha universal (nativo e web).

Mixins

Como utilizamos no pré-processador SASS (meu preferido.. :D), os mixins são uma boa saída para reaproveitamento de código e organização:

1
2
3
4
export const errorText = {
fontWeight: "700",
color: "red",
};
1
2
3
4
5
6
7
8
9
10
11
12
import { errorText } from "textMixins";

export default StyleSheet.create({
formErrorMessage: {
...errorText,
fontSize: 22,
},
fieldErrorMessage: {
...errorText,
fontSize: 18,
},
});

Estilo global

Como em muitas metodologias de CSS, temos uma boa organização definido o estilo primitivo e o reutilizando em suas folhas de estilo. Ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export const COLOR_BLUE = "blue";
export const COLOR_RED = "red";
// ...

export default StyleSheet.create({
blue: { color: COLOR_BLUE },
red: { color: COLOR_RED },
// ...
bg_blue: { backgroundColor: COLOR_BLUE },
bg_red: { backgroundColor: COLOR_RED },
// ...
o_100: { opacity: 1 },
o_90: { opacity: 0.9 },
o_80: { opacity: 0.8 },
// ...
});

Podendo ser usado assim:

1
2
3
4
5
6
7
8
9
10
11
import styles from "styles";

class MyComponent extends React.Component {
render() {
return (
<View style={styles.bg_red}>
<Text style={[styles.blue, styles.o_90]}>Text</Text>
</View>
);
}
}

Ou assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { COLOR_BLUE, COLOR_RED } from "styles";

class MyComponent extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>Text</Text>
</View>
);
}
}

const styles = {
container: {
backgroundColor: COLOR_BLUE,
},
text: {
color: COLOR_RED,
}
}

Teste e busque a melhor solução para o seu projeto. Aqui veremos só algumas possibilidades. Então descubra o seu problema e comece a pensar na solução para a arquitetura.

Muitas vezes, mesmo uma pequena mudança na forma como um componente funciona, significa que os nomes dos estilos não se encaixam. E os problemas podem aparecer e prejudicar o projeto. Então gaste um tempo, testando a necessidade do projeto e a melhor solução de organização e utilização.

Funções auxiliares

Estilos em JavaScript significa que você obtém o poder de uma linguagem de programação em vez de uma linguagem de estilo simples.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// font https://gist.github.com/samueljmurray/eeb9495146ef0aad24f534cecd17487c
import { Dimensions } from "react-native";

// Height
const screenSizes = [
{
name: "xs",
height: 568
},
{
name: "s",
height: 667
}
];

// Example usage:
// screenSize({xs: 8, s: 12}, 16)
// screenSize({s: 12}, 16)
// screenSize({xs: 8}, 16)
export function screenSize(screenSizeOptions, defaultValue) {
const matchedScreenSizes = screenSizes.filter((screenSize) => {
return Dimensions.get("window").height < screenSize.height;
});

let value;
const hasScreenSizeOption = matchedScreenSizes.some((matchedScreenSize) => {
if (screenSizeOptions.hasOwnProperty(matchedScreenSize.name)) {
value = screenSizeOptions[matchedScreenSize.name];
return true;
} else {
return false;
}
});
if (!hasScreenSizeOption) {
value = defaultValue;
}
return value;

Passando contexto para o estilo

Um componente <Button />, por exemplo, pode aceitar uma propriedade de cor (string) e estilo quando estiver desabilitado (booleano), que afetam o seu estilo:

1
2
3
4
5
6
7
8
export default StyleSheet.create({
button: {
backgroundColor: "red",
},
buttonDisabled: {
backgroundColor: "gray",
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import styles from "buttonStyles";

class Button extends React.Component {
render() {
return (
<View style={[
styles.button,
this.props.color && {
backgroundColor: this.props.color
},
this.props.disabled && styles.buttonDisabled,
]}>
// ...
</View>
);
}
}

O problema do exemplo acima, que pode ficar muita lógica misturada (estilo e funcionalidade do componente). Então, vamos deixar a lógica de estilo no seu devido lugar.

1
2
3
4
5
6
7
8
9
10
11
12
13
export default (props) => StyleSheet.create({
button: StyleSheet.flatten([
{
backgroundColor: "red",
},
props.color && {
backgroundColor: props.color,
},
props.disabled && {
backgroundColor: "gray",
},
]),
});
1
2
3
4
5
6
7
8
9
10
11
12
import styles from "buttonStyles";

class Button extends React.Component {
render() {
const s = styles(this.props);
return (
<View style={s.button}>
// ...
</View>
);
}
}

Mais um exemplo, sem StyleSheet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Button extends React.Component {
render() {
const s = styles(this.props);
return (
<View style={s.button}>
// ...
</View>
);
}
}

const styles = props => ({
button: {
backgroundColor: props.disabled ? "gray": (props.color ? props.color : "red"),
},
});

Ficou mais complexo. Simplificando ficaria assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Button extends React.Component {
render() {
const { color, disabled } = this.props;
const buttonStyle = disabled ? styles.button({ color }) : styles.buttonDisabled;
return (
<View style={buttonStyle}>
// ...
</View>
);
}
}

const styles = {
button: props => ({
backgroundColor: props.color ? props.color : "red",
},
buttonDisabled: {
backgroundColor: "gray",
}
});

Esses foram exemplos que seguirmos uma linha antes de avaliar bem o projeto, pode ficar muito complexo, independente do caminho escolhido. O melhor caminho é ver na prática e testar as possibilidades que conseguir.

Conclusão

Testando as abordagens ao estilo no React native, podemos ver a flexibilidade e também muda a forma como pensamos sobre como os estilos podem ser definidos em aplicações baseadas em componentes JavaScript, não apenas no React Native, mas também na web.

Tem muitas bibliotecas para testar:

Então, vamos testar!

Ao fechar este aviso ou continuar navegando no site Nerd Calistênico, você aceita o uso de cookies.

Este site usa cookies para assegurar a melhor experiência para os nossos usuários. Consulte nossa política de privacidade.

Uma nova versão está disponível. Clique aqui para atualizar.