I'm relatively new to React. I want to make a function that call items data from Firebase using a list of ids.
I use TypeScript, React Native and Hooks.
I try the following code :
const FavoritesScreen = () => {
const [favoritesData, setFavoritesData] = useState<Array<Item>>([])
useEffect(() => {
init()
}, [])
const init = async () => {
const data = await getFavorites(sortByTimeStamp)
setFavoritesData(data)
}
// ...
Someone recommended me to put the declaration of the init function out of the useEffect hook when using async/await. It is working so far.
getFavorites is declared with async as it needs to await data from Firebase.
Visual Studio underline the word data in setFavorites(data) with the following comment:
const data: Promise<Item | undefined>[]
Argument of type 'Promise<Item | undefined>[]' is not assignable to parameter of type 'SetStateAction<Item[]>'.
Type 'Promise<Item | undefined>[]' is not assignable to type 'Item[]'.
Type 'Promise<Item | undefined>' is missing the following properties from type 'Item': author, authorName, authorTitle, benefits, and 13 more.ts(2345)
It is not clear for me if the issue is the promise or the undefined, neither how to fix it.
Here is the full code if it can help:
import React, { useEffect, useState, useContext } from 'react'
import { Text, SafeAreaView, StyleSheet } from 'react-native'
import colors from '../constants/colors'
import { FirebaseContext, FavoritesContext } from 'src/firebase'
import { Item } from '../types/item'
import { Timestamp } from '@firebase/firestore-types'
type CompareFunction = (a: [string, Timestamp], b: [string, Timestamp]) => number
const FavoritesScreen = () => {
const { firebase } = useContext(FirebaseContext)
const { favorites } = useContext(FavoritesContext)
const [favoritesData, setFavoritesData] = useState<Array<Item>>([])
useEffect(() => {
init()
}, [])
const init = async () => {
// call the functions used in useEffect
const data = await getFavorites(sortByTimeStamp)
setFavoritesData(data)
}
// This function gets Firestore data for one id
const getItemDataFromId = async (id: string) => {
try {
const data: Item = await firebase.db.collection('content').doc(id).get().data()
return data
} catch (error) {
console.log(`Could not get Firebase data from Id: ${id}. Error message: ${error}`)
}
}
// this function compare the timestamps for use in the Array.prototype.sort() method.
function sortByTimeStamp(a: [string, Timestamp], b: [string, Timestamp]) {
let am = 1
let bm = 1
try {
const am = a[1].toMillis()
} catch {
return -1
}
try {
const bm = b[1].toMillis()
} catch {
return 1
}
return am - bm
}
// Create an array of items data from the favorites object, sorted ny timestamp
const getFavorites = async (compareFunction?: CompareFunction) => {
// Convert the object to a [[key1, value1],[key2,value2],...) array
const favoritesArray = Object.entries(favorites)
// sort if needed
compareFunction && favoritesArray.sort(compareFunction)
// get the data from firebase
const items = favoritesArray.map(async ([key, value]) => await getItemDataFromId(key))
return items
}
return (
<SafeAreaView style={styles.container}>
<Text>Work in progress</Text>
</SafeAreaView>
)
}
//// Styles ////
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.background,
justifyContent: 'center',
alignItems: 'center',
},
})
export default FavoritesScreen