germanosilva.dev

Como passar dados através de componetes React Native

Em React Native/Expo, passar dados sem usar o getContext (ou a API de Contexto) normalmente envolve prop drilling (passar dados através de propriedades) ou o uso de bibliotecas de gerenciamento de estado. Aqui está uma explicação detalhada de como passar dados entre componentes sem usar o Context API, junto com exemplos práticos:

1. Passagem de Dados por Propriedades (Prop Drilling)

A maneira mais direta de compartilhar dados entre componentes é passando-os diretamente de um componente pai para um componente filho através das props. Esse processo é conhecido como prop drilling.

No entanto, o prop drilling pode se tornar complicado quando você precisa passar dados por muitos componentes aninhados.

Exemplo: Prop Drilling

Neste exemplo, passamos dados do componente raiz App para um componente UserDisplay.

import React, { useState } from 'react';
import { Text, Button, View } from 'react-native';

// Componente Filho
const UserDisplay = ({ user, setUser }) => {
  return (
    <View>
      <Text>Usuário Atual: {user}</Text>
      <Button title="Trocar Usuário" onPress={() => setUser("Jane Doe")} />
    </View>
  );
};

// Componente Intermediário
const IntermediateComponent = ({ user, setUser }) => {
  return (
    <View>
      <Text>Componente Intermediário</Text>
      <UserDisplay user={user} setUser={setUser} />
    </View>
  );
};

// Componente Raiz
export default function App() {
  const [user, setUser] = useState("John Doe");

  return (
    <View>
      <Text>Componente App</Text>
      <IntermediateComponent user={user} setUser={setUser} />
    </View>
  );
}

Explicação:

  • O estado user é mantido no componente App.
  • O user e a função setUser são passados para o IntermediateComponent, que por sua vez os passa para o componente UserDisplay.
  • Embora seja simples para árvores de componentes pequenas, esse método pode ser complexo quando muitos componentes precisam de dados.

2. “Lifting State Up” (Elevar o Estado)

Elevar o estado é um padrão onde você move o estado para o ancestral comum mais próximo dos componentes que precisam dele.

Exemplo: Lifting State Up

Aqui, dois componentes irmãos compartilham o mesmo estado por meio de um componente pai.

import React, { useState } from 'react';
import { Text, Button, View } from 'react-native';

// Componente Filho 1
const UserDisplay = ({ user }) => {
  return (
    <View>
      <Text>Usuário Atual: {user}</Text>
    </View>
  );
};

// Componente Filho 2
const UserChange = ({ setUser }) => {
  return (
    <View>
      <Button title="Trocar Usuário" onPress={() => setUser("Jane Doe")} />
    </View>
  );
};

// Componente Pai
export default function App() {
  const [user, setUser] = useState("John Doe");

  return (
    <View>
      <UserDisplay user={user} />
      <UserChange setUser={setUser} />
    </View>
  );
}

Explicação:

  • O estado user e a função setUser são mantidos no componente App e passados para os dois componentes filhos.
  • Um componente exibe o nome do usuário, enquanto o outro altera o nome do usuário.
  • Esse padrão evita a repetição de estados e permite que múltiplos componentes compartilhem o mesmo estado.

3. Uso de Bibliotecas de Gerenciamento de Estado (Redux, Zustand, etc.)

Em aplicações maiores, o prop drilling ou o “lifting state up” podem se tornar difíceis de gerenciar. Nesse caso, usar bibliotecas como Redux ou Zustand ajuda a organizar o estado da aplicação.

Exemplo: Passando Dados com Redux

Com o Redux, o estado é mantido em um estado global acessível a qualquer componente, sem a necessidade de passar props manualmente.

Exemplo Simplificado com Redux:

import React from 'react';
import { Text, Button, View } from 'react-native';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { createStore } from 'redux';

// Estado inicial
const initialState = {
  user: "John Doe"
};

// Função reducer
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "SET_USER":
      return { ...state, user: action.payload };
    default:
      return state;
  }
};

// Criação da store
const store = createStore(reducer);

// Componente para exibir o usuário
const UserDisplay = () => {
  const user = useSelector((state) => state.user);
  return (
    <View>
      <Text>Usuário Atual: {user}</Text>
    </View>
  );
};

// Componente para alterar o usuário
const UserChange = () => {
  const dispatch = useDispatch();
  return (
    <View>
      <Button title="Trocar Usuário" onPress={() => dispatch({ type: "SET_USER", payload: "Jane Doe" })} />
    </View>
  );
};

// Componente raiz com o Redux Provider
export default function App() {
  return (
    <Provider store={store}>
      <View>
        <UserDisplay />
        <UserChange />
      </View>
    </Provider>
  );
}

Explicação:

  • O Redux armazena o estado global da aplicação.
  • O useSelector permite que componentes leiam o estado da store global.
  • O useDispatch permite que componentes enviem ações para atualizar o estado.

Comparação de Métodos

MétodoDescriçãoQuando Usar
Prop DrillingDados são passados de um componente pai para os filhos via props.Ideal para hierarquias simples ou quando poucos componentes precisam dos dados.
Lifting State UpO estado é movido para o ancestral comum mais próximo dos componentes que precisam compartilhá-lo.Útil quando componentes no mesmo nível hierárquico precisam de acesso ao mesmo estado.
Redux/ZustandCria um estado global acessível por qualquer componente sem a necessidade de passar props manualmente.Melhor para grandes aplicações com muitos componentes compartilhando o mesmo estado.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *