React Native - context + firebase - react-native

I need to pass one value from firestore to application context. I don't know where am I going wrong? Has anyone had a similar problem? I searched the website but couldn't find anything similar.
export const AuthProvider = ({children}) => {
const [user, setUser] = useState();
const [contextWeight, setContextWeight] = useState();
}
return (
<AuthContext.Provider
value={{
user,
setUser,
contextWeight,
setContextWeight,
unit: async () => {
await firestore()
.collection('users')
.doc(auth().currentUser.uid)
.collection('products')
.doc('product')
.get()
.then(( documentSnapshot ) => {
if( documentSnapshot.exists ) {
setContextWeight(documentSnapshot.data().weightUnit);
}
}).catch(error => {
console.log(error);
})
}}>
{children}
</AuthContext.Provider>
);

Related

Why is the data in a Context not updating/completing/getting passed down

I use the following code to fetch the data for my app.
export const DataContext = () => {
const [posts, setPosts] = useState<Array<Post>>([]);
const [profiles, setProfiles] = useState<Array<User>>([]);
const [page, setPage] = useState<number>(1);
const [perPage, setPerPage] = useState<number>(10);
useEffect(() => {
async function fetchData() {
const { data: postsData } = await supabase
.from("posts")
.select("*")
.range((page - 1) * perPage, page * perPage - 1);
setPosts(postsData!.map((post) => new Post(post)));
const postUids = postsData!.map((post) => post.uid);
const { data: profilesData } = await supabase
.from("profiles")
.select("*")
.in("uid", postUids);
const profiles = profilesData!.map((userData: any) => {
const userPosts = posts.filter((post) => post.uid === userData.uid);
const user = new User({ ...userData, posts: userPosts });
return user;
});
setProfiles((prevUsers) => [...prevUsers, ...profiles]);
}
fetchData();
}, [page, perPage]);
const nextPage = () => {
setPage(page + 1);
};
const prevPage = () => {
setPage(page - 1);
};
return React.createContext({ posts, profiles, nextPage, prevPage });
};
Then, in a TabBarView I use that context to share the data between two screens.
const { posts, profiles } = useContext(DataContext());
const Home = (props: any) => (
<View style={Theme().screen}>
<HomeScreen posts={posts} users={users} />
</View>
);
const Discover = (props: any) => (
<View style={Theme().screen}>
<ExploreScreen posts={posts} users={profiles} />
</View>
);
My first issue was that the posts array in each user was always empty in the context. I fixed this temporarily by repeating the logic to add those posts in the TabBarView.
const { posts, profiles } = useContext(DataContext());
const users: Array<User> = profiles.map((user) => { ///Added
const userPosts = posts.filter((post) => post.uid === user.uid); ///Added
user.posts.push(...userPosts); ///Added
return user; ///Added
}); ///Added
const Home = (props: any) => (
<View style={Theme().screen}>
<HomeScreen posts={posts} users={users} />
</View>
);
const Discover = (props: any) => (
<View style={Theme().screen}>
<ExploreScreen posts={posts} users={profiles} />
</View>
);
Even though that data is now logging what I would expect, the data going to HomeScreen and DiscoverScreen through props is different. The posts is fine but users is just logging as [] which means the users are not added there. Why is this happening and how can I fix this?
Example data from DataContext:
Posts: [{
"caption":"Caption",
"date":"1669244422569",
"imageUrls":[
"https://cdn.pixabay.com/photo/2020/05/04/16/05/mckenzie-river-5129717__480.jpg"
],
"location":{
"latitude":150,
"locationInfo":"City, State",
"longitude":-150
},
"postId":"1669244407166",
"uid":"daf6b8be-7cd0-4341-89d7-07879b207087"
}]
Users: [{
"blockedUsers":[],
"displayName":"name",
"photoURL":"https://cdn.pixabay.com/photo/2020/05/04/16/05/mckenzie-river-5129717__480.jpg",
"uid":"daf6b8be-7cd0-4341-89d7-07879b207087",
"verified":false
}]
Example log from TabBarView:
Posts: [Post, Post, Post]
Users: [User, User, User]
What would log in HomeScreen:
Posts: [Post, Post, Post]
Users: []

Promise Rejection with axios. try to make HTTP instead of HTTPs [ duplicate ]

I pull data from the API and write it to the application with usestate() when the app runs there are no problems, but after 10-30 seconds I get this error.
Here is my code.
const App = () => {
const [datas, setDatas] = useState([])
const res = async () => {
const response = await axios.get("http://hasanadiguzel.com.tr/api/kurgetir")
setDatas(response.data.TCMB_AnlikKurBilgileri)
}
res()
return (
<SafeAreaView style={style.container}>
<View>
{datas.map((item) => {
return (
<KurCard
title={item.Isim}
alis={item.BanknoteBuying}
satis={item.BanknoteSelling}
/>
)
})}
</View>
</SafeAreaView>
)
}
How can I fix this ?
Hi #n00b,
The problem is with your URL Protocol.
const App = () => {
const [datas, setDatas] = useState([]);
const res = async () => {
try {
const url = "https://hasanadiguzel.com.tr/api/kurgetir";
const response = await axios.get(url);
const data = await response.data;
console.log(data.TCMB_AnlikKurBilgileri); // check you console.
setDatas(response.data.TCMB_AnlikKurBilgileri);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
res();
}, []);
And also check this out:- Codesandbox.
And please read this Stack Overflow discussion for better understanding:- stackoverflow

Flatlist is very slow in using big data in react native

i have a big data list of products thats paginate, in every page it load 10 item, but when i add new items to itemlist,flatlist gets very slow,As the number of pages increases, so does the loading time of new products,The function of the choose button is also slowed down.
How to speed up loading I tried all the best methods but it still did not work. Did not React Native really solve this problem?
export default function Products(props) {
const toast = useToast();
const [isLoading, setSetIsLoading] = useState(true);
const [items, setItems] = useState([]);
const [fetchStatus, setFetchStatus] = useState(false);
const [page, setPage] = useState(1);
const [sending, setSending] = useState(false);
async function getProducts() {
let token = await AsyncStorage.getItem('#token');
let data = {
token: token,
page: page,
};
await get_products(data)
.then(res => {
setItems([...items, ...res.data.data.docs]);
setPage(res.data.data.nextPage);
})
.catch(err => {
console.log(err);
});
}
async function getNextPage() {
let token = await AsyncStorage.getItem('#token');
let data = {
token: token,
page: page,
};
await get_products(data)
.then(res => {
setItems([...items, ...res.data.data.docs]);
setPage(res.data.data.nextPage);
})
.catch(err => {
console.log(err);
});
}
async function selectProduct(id) {
setSending(true);
console.log({id});
let token = await AsyncStorage.getItem('#token');
let data = {
product_id: id
};
await select_products(data,token).then(res => {
toast.show({
description:res.data.message
})
setSending(false);
}).catch(rej => {
console.log({rej})
toast.show({
description:rej?.response?.data.message,
})
setSending(false);
})
}
useFocusEffect(
React.useCallback(() => {
getProducts();
return () => {
setItems([]);
setPage();
};
}, []),
);
renderItem =({item}) => (
<Card
selectProduct={id => selectProduct(id)}
sending={sending}
obj={item}
/>
)
return (
<View mb={20}>
<FlatList
data={items}
extraData={items}
removeClippedSubviews={true}
renderItem={renderItem}
keyExtractor={(item) => `${item._id}-item`}
onEndReached={getNextPage}
maxToRenderPerBatch="13"
ListFooterComponent={() => {
return <ActivityIndicator color="orange" size="large" />;
}}></FlatList>
</View>
);
}
Did you use **map method **?
It can help you for more easily loading data

react native - why is my console.log returning [] but items get rendered on screen?

I am trying to access the object obtained from my API get request but I keep getting Array[] returned in the console.log while the items get rendered on the screen.
Can someone spot where I went wrong?
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await messagesApi.getMessages();
setLoading(false);
if (refreshing) setRefreshing(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data);
};
useEffect(() => {
const newsocket = io.connect("http://ip:port");
loadPosts();
console.log(posts); // not working
newsocket.on("connect", (msg) => {
setSocket(newsocket);
});
return () => newsocket.close();
}, []);
return (
<FlatList
data={posts}
keyExtractor={(post) => post.id.toString()}
renderItem={({ item, index }) => (
<MessagesList
title={item.title}
onPress={() =>
navigation.navigate(routes.CHAT, { message: item, index, updateView })
}
/>
)}
/>
);
ISSUE
console.log executes before getting an API response.
SOLUTION
console.log would work when you add posts in dependency like
useEffect(() => {
console.log(posts);
}, [posts]); // added posts here

React Native User Login Problem ( AsyncStorage )

I am trying to make a membership login system but I get an error. I couldn't understand much because I had just started. What's the problem?
export default async () => {
const [isLoading, setIsLoading] = React.useState(true);
const [userToken, setUserToken] = React.useState(null);
const AsyncUserValue = await AsyncStorage.getItem('userid');
console.log(AsyncUserValue); // (userid 15)
if(AsyncUserValue != null){
console.log('AsyncStorageParse: ' + AsyncUserValue); // (userid 15)
setUserToken(AsyncUserValue);
console.log('Tokken: ' + userToken); // NULL
}
React.useEffect(() => {
setTimeout(() =>{
setIsLoading(false);
}, 1000);
}, []);
if(isLoading) { return <SplashScreen /> }
return(
<NavigationContainer>
{userToken ? (
<AppTabs />
) : (
<LoginStack />
) }
</NavigationContainer>
)
}
You returned functional component as asynchronous (note top export default async ()).
You can't do that - components are required to return React elements (so they have to be synchronous).
What you can do instead is to create a inner async function and do all your async logic there:
export default () => {
const [state, updateState] = useState();
async function myWork() {
const data = await getDataAsyncWay();
updateState(data);
}
useEffect(() => {
myWork()
}, [])
return <View>{...}</View>
}
Note: avoid exporting anonymous function as components - this way, their name won't be visible in stack trace (see your screenshot). What you can do instead is:
function MyComponent() {...};
export default MyComponent