Hoje, vamos explorar o hook useContext de uma maneira simplificada e prática.
Para este exemplo eu iniciei um app react native com o boilerplate a seguir, alterei as rotas para stack e criei duas telas, FirstScreen e Secondscreen. Também atualizei o arquivo de interface das rotas para que tudo funcione como deveria.
https://github.com/AllyssonCidade/boilerplate-expo-app
Vamos ao que interessa...
O que é o useContext e porque ele é importante!
Imagina que você coordena uma equipe de líderes e precisa constantemente passar informações para os líderes e suas respectivas equipes. Em algum momento, acontece aquele velho "telefone sem fio": você passa a informação para um líder, que repassa para os membros da sua equipe, que por sua vez, passam para outros. Quanto mais intermediários entre você e quem realmente precisa da informação, maior a chance de a mensagem se perder ou ser distorcida.
Agora, imagine que, em vez de precisar passar essa informação para cada líder e membro de equipe individualmente, você tivesse uma espécie de "sala de reuniões" (ou uma gaveta compartilhada) onde todos pudessem acessar as informações diretamente, sem depender de intermediários. Isso eliminaria erros de comunicação e deixaria tudo mais eficiente, certo? No React, essa "sala de reuniões" é o useContext.
Com o useContext, você cria um "contexto" global(essa gaveta que falamos anteriormente) onde pode armazenar as informações que serão acessadas por qualquer componente, em qualquer parte da árvore de componentes, sem precisar passar props diretamente de um para outro. Isso simplifica a comunicação e evita a confusão do "telefone sem fio".
Para usar o useContext, primeiro precisamos criar um contexto com o método createContext. Em seguida, esse contexto pode envolver os componentes onde você deseja compartilhar os dados, e finalmente, usar o useContext para acessar esses dados de qualquer componente filho.
Vou mostrar isso na prática, para que fique tudo bem claro.
**
Hora de por a mão na massa!
**
Primeiro, criamos um arquivo contexts para que possamos colocar todos os tipos de contexto que forem necessários. Isso vai manter tudo organizado e facilitar a manutenção e futuras visitas ao código.
Agora, vamos ao arquivo contexts e criaremos nosso primeiro arquivo de contexto, que chamaremos de** ThemeContext.jsx.** Nele, vamos importar createContext e useState:
import { createContext, useState } from 'react';
Também vamos exportar diretamente o ThemeContext (que será o contexto que iremos criar) como uma instância de createContext, assim:
export const ThemeContext = createContext();
Lembrando que também é bem comum dividir em dois arquivos diferentes o Provider e o Context. Nesse caso vou manter no mesmo arquivo pois não vai ter muita coisa.
Também vamos criar o retorno dessa função dentro do provedor do nosso contexto, passando um children como argumento. Esse children será toda a parte da aplicação que vai utilizar este contexto (vamos ver isso acontecendo mais à frente).
return <ThemeContext.Provider>{children}</ThemeContext.Provider>;
Perfeito! Agora estamos com nosso arquivo quase pronto, mas ainda precisamos definir o que realmente será enviado nesse contexto, né? Então, vamos fazer isso agora.
Vamos usar o hook useState para gerenciar o estado. Para isso, vamos criar uma variável theme e um modificador setTheme no useState, e como valor inicial, vamos definir "light":
const [theme, setTheme] = useState('light')
Em seguida, criamos uma função para modificar esses valores:
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light')
}
E também uma variável para gerenciar as propriedades do contexto:
const values = {
theme,
toggleTheme
}
Depois, basta adicionar isso ao nosso ThemeProvider:
return <ThemeContext.Provider value={values}>{children}</ThemeContext.Provider>
Perfeito! Tudo pronto por aqui. Nosso código deve ficar assim:
`import { createContext, useState } from 'react'
export const ThemeContext = createContext()
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light')
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light')
}
const values = {
theme,
toggleTheme
}
return <ThemeContext.Provider value={values}>{children}</ThemeContext.Provider>
}`
**
Próximo passo: englobar toda a parte da aplicação que queremos que receba esse contexto com o provider que criamos.
**
Nesse caso, vai ser tudo mesmo. Podemos fazer isso no arquivo App.jsx ou equivalente; o importante é que englobe tudo o que você deseja (apenas).
Então vamos ao arquivo de rotas. Primeiro, importamos nosso Provider:
import { ThemeProvider } from '../contexts/ThemeContext'
Depois, colocamos ele em volta das rotas. Nesse exemplo, ficará assim:
const AppNavigation = () => {
return (
<ThemeProvider>
<Stack.Navigator>
<Stack.Screen name="FirstScreen" component={FirstScreen} />
<Stack.Screen name="SecondScreen" component={SecondScreen} />
</Stack.Navigator>
</ThemeProvider>
)
}
Bem simples, né?
**
Agora, só precisamos fazer com que nossas telas usem esses dados. Vamos para a primeira tela e, depois, repetimos na segunda.
**
Importaremos o useContext e o contexto que criamos:
import { useContext } from 'react'
import { ThemeContext } from '../../contexts/ThemeContext'
Lembra que lá atrás criamos as props que seriam passadas? Pois bem, elas serão usadas aqui. Então chamamos agora, e como passamos uma função que altera o theme, temos o poder de não só receber os dados, mas também de alterar o valor que está no contexto. Assim, o que for alterado em um local também será no outro.
Vamos criar uma const com o useContext, assim como fazemos com o useState(padrão dos hooks no React)
const { theme, toggleTheme } = useContext(ThemeContext)
Para mostrar a alteração ocorrendo, vou criar um Text para mostrar nosso tema atual e também um botão para alterar o tema usando nosso toggleTheme.
Assim, fica o retorno da tela FirstScreen (coloquei uma cor no botão e um espaço entre eles para facilitar a visualização):
return (
<S.Wrapper testID="wrapper">
<Text>Tema atual: {theme}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('SecondScreen')}
style={{ marginTop: 40, padding: 10, backgroundColor: 'gray', borderRadius: 5 }}
>
<Text>FirstScreen</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => toggleTheme()}
style={{ marginTop: 40, padding: 10, backgroundColor: 'tomato', borderRadius: 5 }}
>
<Text>Alterar Tema</Text>
</TouchableOpacity>
</S.Wrapper>
)
_Agora só repetir isso na outra tela fazendo as adaptações!
_
Bom, aqui já temos nosso contexto funcionando corretamente. Agora para ficar legal vamos adicionar uma cor de fundo para que fique realmente parecendo estar alterando o 'tema'?
**
Let`s Code!
**
Para esse exemplo, vamos criar uma variável de estilos na própria função da tela antes do `return;
const styles = {
light: {
backgroundColor: 'white'
},
dark: {
backgroundColor: 'black'
}
}`
E no S.Wrapper, vamos adicionar o estilo que será usado:
<S.Wrapper style={{ backgroundColor: styles[theme].backgroundColor }} testID="wrapper">
Repetimos isso para as duas telas e temos nossa cor de fundo alterando de acordo com nosso contexto.
Como estamos usando TypeScript, vamos apenas tipar a variável para não quebrar a aplicação. Então, dentro de cada tela, colocamos esta interface:
pode colocar entre os imports e a função da tela propriamente dita.
interface ThemeContextType {
theme: 'light' | 'dark'
toggleTheme: () => void
}
Depois alteramos a chamada do contexto desta forma:
const { theme, toggleTheme } = useContext(ThemeContext) as ThemeContextType
**
Tudo funcionando e nosso contexto foi um sucesso!
**
.........
**
Conclusão
**
Neste artigo, exploramos o hook useContext de maneira prática e simplificada, demonstrando como criar um contexto para gerenciar temas em um aplicativo React Native. Aprendemos a importância do useContext para evitar a complexidade de passar props através de múltiplos níveis de componentes, simplificando a comunicação e garantindo que todos os componentes acessem as informações de maneira eficiente.
Criamos um contexto chamado ThemeContext, que nos permite compartilhar o tema da aplicação (claro ou escuro) entre diferentes telas. Vimos como configurar o provedor de contexto, como consumir esses dados nas telas e, finalmente, como implementar a troca de temas de forma dinâmica.
Vale ressaltar que, embora o useContext seja uma solução poderosa para gerenciar estados globais, existem outras abordagens, como o Redux, que é amplamente utilizado em aplicações de grande escala. Além disso, o hook useMemo pode ser uma excelente opção em situações específicas, onde é necessário otimizar o desempenho ao memorizar valores complexos ou cálculos.
_Espero que tenha sido útil e inspirador! Sinta-se à vontade para experimentar, adaptar e levar essa implementação adiante. Agradeço pela leitura e desejo muito sucesso no seu(nosso) aprendizado!
_
Allysson Cidade
Desenvolvedor Mobile | Front-End.
Top comments (0)