Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6287

How to type promises on react context with typescript

$
0
0

I'm learning to implement typescript in react and I'm struggling trying to implement a couple of async functions on context.

The error I'm getting is the following:

Argument of type '{ userData: null; favoriteCocktails: never[]; publishedRecipes: never[]; fetchUserData: (user: any) => PromiseConstructor; fetchFavoriteCocktails: (userData: UserData | null) => PromiseConstructor; fetchPublishedRecipes: (user: any) => PromiseConstructor; }' is not assignable to parameter of type 'ProfileContext'.  The types returned by 'fetchUserData(...)' are incompatible between these types.    Type 'PromiseConstructor' is missing the following properties from type 'Promise<void>': then, catch, finally, [Symbol.toStringTag]ts(2345)

This is my context:

import { createContext } from 'react'import {UserData , Cocktail} from '../types'interface ProfileContext {    userData: UserData | null,    favoriteCocktails: Array<Cocktail>,    publishedRecipes: Array<Cocktail>,    fetchUserData: (user: any) => Promise<void>,    fetchFavoriteCocktails: (userData: UserData | null) => Promise<void>,    fetchPublishedRecipes: (user: any) => Promise<void>,}const defaultState = {    userData: null,    favoriteCocktails: [],    publishedRecipes: [],    fetchUserData: (user: any) => Promise,    fetchFavoriteCocktails: (userData: UserData | null) => Promise,    fetchPublishedRecipes: (user: any) => Promise}const ProfileContext = createContext<ProfileContext>(defaultState)export default ProfileContext

This is my provider:

import ProfileContext from './ProfileContext'import { query, where, getDocs, collection } from 'firebase/firestore'import { db } from '../services/firebase.config'import { Cocktail, UserData } from '../types'import { useState } from 'react'export default function ProfileContextProvider ({ children }: { children: any }) {  const [userData, setUserData] = useState<UserData | null>(null)  const [favoriteCocktails, setFavoriteCocktails] = useState<Array<Cocktail>>([])  const [publishedRecipes, setPublishedRecipes] = useState<Array<Cocktail>>([])  const fetchUserData = async (user: any) => {    try {      const q = query(collection(db, 'mixrUsers'), where('email', '==', user.email))       const querySnapshot = await getDocs(q)      const result: any[] = []      querySnapshot.forEach(doc => result.push(doc.data()) )      setUserData(result[0])          } catch (err) {      console.error(err)    }  }  const fetchFavoriteCocktails = async (userData: UserData | null) => {    try {      const q = query(collection(db, 'mixrCocktails'), where('id', 'in', userData?.favoriteCocktails))         const querySnapshot = await getDocs(q)      const result: any[] = []      querySnapshot.forEach(doc => {result.push(doc.data())} )      setFavoriteCocktails(result)    } catch (err) {      console.error(err)    }  }  const fetchPublishedRecipes = async (user: any) => {    try {      console.log('fetchPublishedRecipes')      const q = query(collection(db, 'mixrCocktails'), where('publisherId', '==', user?.uid))         const querySnapshot = await getDocs(q)      const result: any[] = []      querySnapshot.forEach(doc => result.push(doc.data()) )      setPublishedRecipes(result)          } catch (err) {      console.error(err)    }  }  return (<ProfileContext.Provider value={{ userData, favoriteCocktails, publishedRecipes, fetchUserData, fetchFavoriteCocktails, fetchPublishedRecipes  }} >          {children}</ProfileContext.Provider>  )}

And I'm consuming it on different components in the following ways:

import { useEffect, useContext } from 'react'import ProfileContext from '../context/ProfileContext'import { RootTabScreenProps } from '../types'import { useAuthState } from 'react-firebase-hooks/auth'import { auth } from '../services/firebase.config'import { StyleSheet, Text, View, SafeAreaView, ScrollView, Image, TouchableOpacity } from 'react-native'import CocktailCard from '../components/home/cocktailCard/CocktailCard'import GenericAvatar from '../assets/images/genericAvatar.jpg'export default function ProfileScreen({ navigation }: RootTabScreenProps<'Profile'>) {  /* TODO - Profile context functions break */  const [user] = useAuthState(auth as any)  const {userData, favoriteCocktails, publishedRecipes, fetchUserData, fetchFavoriteCocktails, fetchPublishedRecipes} = useContext(ProfileContext)  useEffect(() => {    fetchUserData(user)    fetchPublishedRecipes(user)  }, [publishedRecipes])  useEffect(() => { if(userData) fetchFavoriteCocktails(userData) },[userData, favoriteCocktails])  /* ====================================== */  return (<SafeAreaView style={styles.container}><ScrollView><View style={styles.profileHeader}><Image style={styles.profilePicture} source={user ? { uri: user?.photoURL } : GenericAvatar}/><Text style={styles.profileName}>{user?.displayName}</Text></View>          ...
import { useContext, useEffect } from 'react'import ProfileContext from '../context/ProfileContext'import { RootTabScreenProps } from '../types'import { useAuthState } from 'react-firebase-hooks/auth'import { auth } from '../services/firebase.config'import { Text, StyleSheet, View } from 'react-native'import CocktailCard from '../components/home/cocktailCard/CocktailCard'export default function PublishedRecipesScreen({ navigation }: RootTabScreenProps<'Published recipes'>) {/* TODO - Profile context functions break */const [user] = useAuthState(auth as any)const { publishedRecipes, fetchPublishedRecipes } = useContext(ProfileContext)useEffect(() => {fetchPublishedRecipes(user)}, [])/* ====================================== */  return (<View style={styles.container}><Text style={styles.title}>Published recipes</Text><View style={styles.cardsContainer}>        {publishedRecipes.map((cocktail, i) => <CocktailCard key={i} cocktail={cocktail} navigation={navigation} />)}</View>      ...

I understand there is a conflict between the types I'm declaring on the context file, and the actual types the functions are returning. But I don't understand how should I declare them.

This functions fetch data from a DB and update a state, so they don't return anything.

I've tried fetchUserData: (user: any) => void, but I get Expression expected.ts(1109)

What's the right way to type this kind of functions?

Full code can be found here: https://github.com/coccagerman/mixr/

Thanks in advance!


Viewing all articles
Browse latest Browse all 6287

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>