# React Native
URL: /docs/examples/react-native.mdx

Integre a API brapi.dev em aplicações React Native. Componentes para exibir cotações de ações da B3 em apps mobile.

***

title: 'React Native'
description: >-
Integre a API brapi.dev em aplicações React Native. Componentes para exibir
cotações de ações da B3 em apps mobile.
full: false
keywords: brapi, api, react native, mobile, cotações, hooks
openGraph:
title: Integração React Native - brapi.dev
description: Componentes React Native para cotações da B3
type: website
locale: pt\_BR
lastUpdated: '2025-10-12T17:30:00.000Z'
lang: pt-BR
howToSteps:

* name: 'Crie um componente de cotação'
  text: 'Crie um componente StockPrice que recebe ticker como prop e usa useState para gerenciar preço, loading e erro.'
* name: 'Implemente useEffect para buscar dados'
  text: 'Use useEffect com fetch para chamar [https://brapi.dev/api/quote/\{ticker}?token=SEU\_TOKEN](https://brapi.dev/api/quote/\{ticker}?token=SEU_TOKEN) e atualizar o estado com os dados retornados.'
* name: 'Adicione tratamento de loading e erro'
  text: 'Renderize ActivityIndicator durante loading e mensagem de erro quando houver falha na requisição.'
* name: 'Estilize o componente com StyleSheet'
  text: 'Use StyleSheet.create para definir estilos do card, incluindo cores para variação positiva (verde) e negativa (vermelho).'
* name: 'Opcionalmente, crie um custom hook useBrapiQuote'
  text: 'Extraia a lógica de fetch para um hook reutilizável que retorna { data, loading, error } para uso em múltiplos componentes.'
  howToTools:
* 'React Native'
* 'Expo ou React Native CLI'
* 'Editor de código'
  howToSupplies:
* 'Projeto React Native configurado'
* 'Conta brapi.dev'
* 'Token de API brapi.dev'

***

Integre a API brapi.dev em suas aplicações React Native.

## Componente Básico

```javascript
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, ActivityIndicator } from 'react-native';

const StockPrice = ({ ticker }) => {
  const [price, setPrice] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const token = 'SEU_TOKEN';
    const fetchPrice = async () => {
      try {
        const response = await fetch(
          `https://brapi.dev/api/quote/${ticker}?token=${token}`
        );
        
        if (!response.ok) {
          throw new Error('Erro ao buscar cotação');
        }
        
        const data = await response.json();
        setPrice(data.results[0]);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchPrice();
  }, [ticker]);

  if (loading) {
    return (
      <View style={styles.container}>
        <ActivityIndicator size="large" color="#0066cc" />
      </View>
    );
  }

  if (error) {
    return (
      <View style={styles.container}>
        <Text style={styles.error}>{error}</Text>
      </View>
    );
  }

  if (!price) return null;

  const isPositive = price.regularMarketChangePercent > 0;

  return (
    <View style={styles.container}>
      <Text style={styles.ticker}>{price.symbol}</Text>
      <Text style={styles.name}>{price.shortName}</Text>
      <Text style={styles.price}>
        R$ {price.regularMarketPrice.toFixed(2)}
      </Text>
      <Text style={[styles.change, isPositive ? styles.positive : styles.negative]}>
        {isPositive ? '+' : ''}{price.regularMarketChangePercent.toFixed(2)}%
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 16,
    backgroundColor: '#ffffff',
    borderRadius: 12,
    marginBottom: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  ticker: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#333',
  },
  name: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  price: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#000',
    marginTop: 8,
  },
  change: {
    fontSize: 16,
    fontWeight: '600',
    marginTop: 4,
  },
  positive: {
    color: '#10b981',
  },
  negative: {
    color: '#ef4444',
  },
  error: {
    color: '#ef4444',
    fontSize: 14,
  },
});

export default StockPrice;
```

## Com Custom Hook

```javascript
import { useState, useEffect } from 'react';

const useBrapiQuote = (ticker, token) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let isMounted = true;

    const fetchQuote = async () => {
      try {
        const response = await fetch(
          `https://brapi.dev/api/quote/${ticker}?token=${token}`
        );
        
        if (!response.ok) {
          throw new Error(`HTTP ${response.status}`);
        }
        
        const json = await response.json();
        
        if (isMounted) {
          setData(json.results[0]);
          setError(null);
        }
      } catch (err) {
        if (isMounted) {
          setError(err.message);
          setData(null);
        }
      } finally {
        if (isMounted) {
          setLoading(false);
        }
      }
    };

    fetchQuote();

    return () => {
      isMounted = false;
    };
  }, [ticker, token]);

  return { data, loading, error };
};

// Uso
const StockCard = ({ ticker }) => {
  const { data, loading, error } = useBrapiQuote(ticker, 'SEU_TOKEN');

  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Erro: {error}</Text>;
  if (!data) return null;

  return (
    <View>
      <Text>{data.symbol}: R$ {data.regularMarketPrice.toFixed(2)}</Text>
    </View>
  );
};
```

## Lista de Cotações

```javascript
import React from 'react';
import { FlatList, View } from 'react-native';

const StockList = () => {
  const tickers = ['PETR4', 'VALE3', 'ITUB4', 'BBDC4', 'MGLU3'];

  return (
    <FlatList
      data={tickers}
      keyExtractor={(item) => item}
      renderItem={({ item }) => <StockPrice ticker={item} />}
      contentContainerStyle={{ padding: 16 }}
    />
  );
};
```

## Próximos Passos

* Veja exemplos em [TypeScript](/docs/examples/typescript)
* Explore [outros exemplos](/docs/examples)


