React Native - Stock API
This lesson is part of a series on React Native.
Step 14 Stock API calls
Make sure you've gone through the alpha-vantage-samples.html sample code before starting this.
- Get an API key from Alpha Vantage (https://www.alphavantage.co/support/#api-key)
- Check out the documentation for more details( https://www.alphavantage.co/documentation/)
- The free version gives you 25 API calls per day, so use them wisely
Create an .env file (if you dont' already have one) in the project root folder (this file will be ignored from the repo - look at the .gitignore file) Add your API key like so:
EXPO_PUBLIC_ALPHA_VANTAGE_API_KEY="PUT YOUR KEY HERE"
Note: remember to prefix your env variable name with EXPO_PUBLIC_
Install Axios (if you have not yet installed it for the project):
npm install axios
Create an api folder in the project root (if you have not already created it)
Create a file named stock-api.js file into the api folder and add this code to the file:
import axios from "axios";
const BASE_URL="https://www.alphavantage.co/query";
export async function getQuote(symbol) {
try {
const response = await axios.get(BASE_URL, {
params: {
function: "GLOBAL_QUOTE",
symbol: symbol,
apikey: process.env.EXPO_PUBLIC_ALPHA_VANTAGE_API_KEY
}
});
//console.log(response.data)
return response.data["Global Quote"];
} catch (error) {
console.error("Error fetching data:", error);
}
}
Update nyse.jsx to look like this:
import { StyleSheet, Text, View } from 'react-native'
import {useState} from 'react'
import {getQuote} from '../../api/stock-api'
import { TextInput } from 'react-native-web'
import CustomButton from '../../components/CustomButton'
import CustomScreen from '../../components/CustomScreen'
import CustomText from '../../components/CustomText'
const nyse = () => {
const [symbol, setSymbol] = useState('')
const [quote, setQuote] = useState(null)
const handleGetQuote = async () => {
if (!symbol) return
const response = await getQuote(symbol)
setQuote(response)
}
return (
<CustomScreen>
{quote && (
<View>
<CustomText title>Symbol: {quote["01. symbol"]}</CustomText>
<CustomText>Open: {quote["02. open"]}</CustomText>
<CustomText>High: {quote["03. high"]}</CustomText>
<CustomText>Low: {quote["04. low"]}</CustomText>
<CustomText>Close: {quote["05. price"]}</CustomText>
</View>
)}
<TextInput
placeholder="Enter stock symbol"
onChange={(e) => setSymbol(e.target.value)}
style={styles.input}
/>
<CustomButton onPress={handleGetQuote}>
<Text style={{color: 'white', textAlign: 'center', fontWeight: 'bold'}} >
Get Quote
</Text>
</CustomButton>
{/* {quote && (<Text>{JSON.stringify(quote)}</Text>)} */}
</CustomScreen>
)
}
export default nyse
const styles = StyleSheet.create({
input:{
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
}
})
Caching Responses
Now let's incorporate a list so we can 'cache' the quotes that we've already made API calls for.
Update nyse.jsx to look like this:
import { Pressable, StyleSheet, Text, View } from 'react-native' ///// Add import for pressable
import {useState} from 'react'
import {getQuote} from '../../api/stock-api'
import { TextInput } from 'react-native-web'
import CustomButton from '../../components/CustomButton'
import CustomScreen from '../../components/CustomScreen'
import CustomText from '../../components/CustomText'
import Spacer from '../../components/Spacer' //// Add import for Pressable
const nyse = () => {
const [symbol, setSymbol] = useState('')
const [quote, setQuote] = useState(null)
const [quoteList, setQuoteList] = useState([]) //////////////// Add this
const handleGetQuote = async () => { ////////////////// update this function
if (!symbol) return
// check to see if we already have this symbol in quoteList
const cachedSymbol = quoteList.find(q => q["01. symbol"] === symbol)
if(cachedSymbol) {
setQuote(cachedSymbol)
return
}else{
const response = await getQuote(symbol)
setQuote(response)
setQuoteList([...quoteList, response])
}
}
return (
<CustomScreen>
{quote && (
<View>
<CustomText title>Symbol: {quote["01. symbol"]}</CustomText>
<CustomText>Open: {quote["02. open"]}</CustomText>
<CustomText>High: {quote["03. high"]}</CustomText>
<CustomText>Low: {quote["04. low"]}</CustomText>
<CustomText>Close: {quote["05. price"]}</CustomText>
</View>
)}
<TextInput
placeholder="Enter stock symbol"
onChange={(e) => setSymbol(e.target.value)}
style={styles.input}
/>
<CustomButton onPress={handleGetQuote}>
<Text style={{color: 'white', textAlign: 'center', fontWeight: 'bold'}} >
Get Quote
</Text>
</CustomButton>
{/* {quote && (<Text>{JSON.stringify(quote)}</Text>)} */}
//////////////////////////////////////////////////////////////// Add this to the jsx:
<Spacer height={25} />
{quoteList.length > 0 && (
<View>
<Text>Quote History:</Text>
{quoteList.map((q, index) => (
<View key={index}>
<Pressable onPress={() => setQuote(q)}>
<CustomText title>
{q["01. symbol"]}
</CustomText>
</Pressable>
</View>
))}
</View>
)}
</CustomScreen>
)
}
export default nyse
const styles = StyleSheet.create({
input:{
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
},
//////////////////////// add this
listItem:{
fontSize: 16,
padding: 5,
}
})