Fetch firebase data before rendering react hook - javascript

I am relatively new to javascript and React and I am helping out with a project. I want to create a profile page for a signed in user with information stored in a firebase real time database. But the component is not rendering and the console shows 'Uncaught TypeError: Cannot read properties of null (reading 'username')'. I surmise it is because the data from the database is not being fetched before rendering. The data exists. The profile hook -
import React, { useEffect,useState } from 'react';
import {useAuth} from '../contexts/AuthContext'
import { getDatabase,ref, onValue} from "firebase/database";
function Profile(){
const [userData, setUserData] = useState({});
const currentUser = useAuth();
useEffect(()=>{ putData()
},[])
async function putData(){
let db = getDatabase();
let refd = ref(db,'users/'+ currentUser.currentUser.uid );
onValue(refd, (snapshot) => {
console.log(snapshot.val());
setUserData(snapshot.val());
},
(errorObject) => {
console.log('The read failed: ' + errorObject.name);
})
}
return(
<div>
<h3>Username : {userData.username}</h3>
<h3>Institute name : {userData.institute_name}</h3>
<h3>Accomodation : {userData.accomodation}</h3>
<h3>Phone no. : {userData.phone}</h3>
<h3>Email : {userData.email}</h3>
</div>
);
}
export default Profile;
Does the problem lie with the 'onValue' part or with the react part? Firebase documentation is not helping with my current understanding. Any help on how to accomplish this is appreciated.

useEffect(() => {
try {
//getting previously saved data
// console.log({ SelectedCaseDetails });
const getData = async () => {
const docRef = doc(
db,
"here comes your path to your document"
);
const docSnap = await getDoc(docRef);
console.log("data -->", docSnap.data());
if (docSnap.exists()) {
setData(docSnap.data());
setData(() => ({ ...docSnap.data() }));
}
};
getData();
} catch (error) {
console.log({ error });
}
}, []);
You just have to run your get data function in useEffect that runs when page is loading
Hope this helps 🤗
¯\(ツ)/¯

Related

Failing to fetch dynamic data from firestore using getStaticPaths in nextjs

When I fetch data from firebase firestore using getStaticProps, it works perfectly but when I try implementing the logic of getting the details of each single item using getStaticPaths, I fail and get a 404 page. This is how my [id].js code looks like currently.
import React from 'react'
import { db } from '#/Firebase';
import {collection, getDoc} from "firebase/firestore";
const reference = collection(db, "abantu");
export const getStaticPaths= async () => {
const umuntu = await getDoc(reference);
const paths = umuntu.docs.map(doc => {
return {
params: { id: doc.id }
}
})
return {
paths,
fallback: false
}
}
export const getStaticProps = async (context) => {
const id = context.params.id;
const data = await getDoc(reference) + id;
return {
props: {
umuntu: data
}
}
}
function Details({umuntu}) {
return (
<div>
<h1>{umuntu.ibizo}</h1>
</div>
)
}
export default Details
I dont quite get where my logic is going wrong but where could I be going wrong?.
For finding the right page props for each of the paths that you generate from the database in the getStaticPaths function, you should be able to find each of the pages information based on the id field you are getting from each path, see it here:
export const getStaticProps = async (context) => {
const id = context.params.id;
const umuntu = await getDoc(reference);
const data = umuntu.docs.find((pageData) => pageData.id === id); // this will find the right page based on the id passed via page path
return {
props: {
data
},
};
};
function Details({ data }) {
return (
<div>
<h1>{data.ibizo}</h1>
</div>
);
}
export default Details;

map function not working in ReactJs using nexttjs

I am new in ReactJS and i am using "Nextjs" framework,Right now i am using "async" function
for fetching data but unable to fetch using "map" function, in console.log ...showing me following message
" items: undefined }",Here is my code,Where i am wrong ?
import React, { Component } from 'react';
const blog =({items}) =>{
console.log({items});
return(
<div>
</div>
);
};
//calling api for get data
export const getstaticprops=async()=>{
console.log('Om Success');
const res=await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json()
return {
props: { items: posts },
}
}
export default blog
test this code !
const blog =({posts}) =>{
console.log(posts); \\ fix console log
return(
<div>
</div>
);
};
export async function getServerSideProps(){
console.log('Om Success');
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json()
return {
props: { posts }, \\ remove items
}
}

TypeError: Cannot read properties of undefined (reading 'map') while setting up MetaMask to display NFT

I keep getting this error when I run my code Uncaught TypeError: Cannot read properties of undefined (reading 'map') I am tring to set up a Metamask which displays the users NFTS that they have purchased from OpenSea when they connect their metamask account I'll show my code to show what I have done and if anyone knows how to fix this could they post a solution code as this would be of so much help.
import { useEffect, useState } from 'react';
import './nft.css'
import NFTContainer from './NFTContainer'
export function Nft() {
const [walletAddress, setWalletAddress] = useState(null)
const [nfts, setNfts] = useState()
const connectWallet = async () => {
if (typeof window.ethereum !== 'undefined') {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
setWalletAddress(accounts[0])
}
}
const getNftData = async () => {
if (!walletAddress) return;
const response = await fetch(`https://api.rarible.org/v0.1/items/byOwner/?owner=ETHEREUM:${walletAddress}`)
const data = await response.json()
debugger
setNfts(data.items)
}
useEffect(() => {
getNftData()
}, [walletAddress])
return (
<div className='Nft'>
<div className='text'>
Account: {walletAddress}
</div>
<button className='connect-button' onClick={connectWallet}>
Connect Wallet
</button>
<NFTContainer nfts={nfts} />
</div>
);
}
export default Nft;
import React from 'react'
import NFTCard from './NFTCard'
const NFTContainer = ({ nfts }) => {
return (
<div>
{nfts.map((nft, index) => {
return <NFTCard nft={nft} key={index} />
})}
</div>
)
}
export default NFTContainer
So when I put in the nft.meta.name I keep getting the uncaught type error and wondering as to why this error keeps appearing
import React from 'react'
const NFTCard = ({ nft }) => {
return (
<div>
{nft.meta.name}
</div>
)
}
export default NFTCard
the problem is you defined your useState like this
const [nfts, setNfts] = useState()
So if you don't define any value to your state then by default it is undefined and you can't map through undefined value, so define your state like this
import { useEffect, useState } from 'react';
import './nft.css';
import NFTContainer from './NFTContainer';
export function Nft() {
const [walletAddress, setWalletAddress] = useState(null);
const [nfts, setNfts] = useState([]);
const connectWallet = async () => {
try {
if (typeof window.ethereum !== 'undefined') {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
setWalletAddress(accounts[0]);
}
} catch (error) {
console.log('err1==>', error);
}
};
const getNftData = async () => {
try {
if (!walletAddress) return;
const response = await fetch(`https://api.rarible.org/v0.1/items/byOwner/?owner=ETHEREUM:${walletAddress}`);
const data = await response.json();
setNfts(data.items);
} catch (error) {
console.log('err2==>', error);
}
};
useEffect(() => {
getNftData();
}, [walletAddress]);
return (
<div className='Nft'>
<div className='text'>Account: {walletAddress}</div>
<button className='connect-button' onClick={connectWallet}>
{!walletAddress ? 'Connect Wallet' : 'Wallet Connected'}
</button>
<NFTContainer nfts={nfts} />
</div>
);
}
export default Nft;
Note: Also do error handling and show loader when API is fetching data from network or from chain
You are missing the initial value here,
const [nfts, setNfts] = useState([]);
You must use the default value while using the useState()hook. If you want to apply array.map() method on state value then have to declare hook with empty array useState([]).

Uncaught TypeError: Cannot destructure property 'connectWallet' of 'useContext(...)' as it is undefined at Welcome (Welcome.jsx)

i'm trying to do a webpage for my Blockchain project and run into JS Mastery youtube web3 tutorial and i'm following it.
I was creating the connect wallet button but I encountered some trouble in importing it from my context.
Below the code:
//inside my prenotationContext.jsx
const PrenotationContext = React.createContext();
export default PrenotationContext;
export const PrenotationProvider = ({children}) => {
const [currentAccount, setCurrentAccount] = useState("");
const [formData, setFormData] = useState({addressTo: "", amount:"", keyword:"", description:"" });
const [isLoading, setIsLoading] = useState(false);
...
const connectWallet = async () => {
try {
if (!ethereum) return alert("Please install MetaMask.");
const accounts = await ethereum.request({ method: 'eth_requestAccounts', });
console.log(accounts)
setCurrentAccount(accounts[0]);
window.location.reload();
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
...
return (
<PrenotationContext.Provider
value={{
connectWallet,
currentAccount,
formData,
sendPrenotation,
handleChange,}}>
{children}
</PrenotationContext.Provider>
);
}
//inside my welcome.jsx
import PrenotationContext from '../context/PrenotationContext.jsx';
...
const Welcome = () => {
// Transfering data from context/PrenotationContext to components
const {connectWallet,currentAccount, formData, sendPrenotation, handleChange} = useContext(PrenotationContext);
...
The error is the following:
Uncaught TypeError: Cannot destructure property 'connectWallet' of 'useContext(...)' as it is undefined at Welcome (Welcome.jsx:25:12)
Btw i'm not a front-end developer and that's my first time using JS and React, so it's not easy for me to find the errors
If you want to call context you should wrapp your component by contextProvider.
const App = () => {
return (
<PrenotationProvider>
// some other components
<Welcome />
// some other components
</PrenotationProvider>
);
};
Put a provider at the high level of application, then you will get all data inside any components

Possible async problem with firebase get request

I have a function useVenue that returns venue data from a call to firebase:
import { useState,useEffect } from 'react'
import { firebase } from './firebaseConfig'
export function useVenues (){
const [venues, setVenues] = useState([]);
useEffect(() => {
const venueArray = [];
const getAllVenues = async () => {
await firebase
.firestore()
.collection("venues")
.get()
.then((snapshot) => {
snapshot.forEach((venue) => {
venueArray.push(venue);
});
setVenues(venueArray);
});
};
getAllVenues();
}, []);
const [...venueData] = venues.map((venue) => {
const {
name,
photoUrl,
averageRating,
numRatings,
type,
address,
phone,
website,
reviews } = venue.data();
return ({
name: name,
photoUrl: photoUrl,
averageRating: averageRating,
numRatings: numRatings,
type: type,
id: venue.id,
reviews:reviews,
address:address,
phone:phone,
website:website
})
});
return {venueData}
};
This function is exported to venues.js where the venue data is destructured out and pass as props to MidSection.js:
venues.js
import { useParams } from 'react-router-dom';
import { useVenues } from '../useVenue';
import Header from '../components/Header'
import VenueDetails from '../components/venue-page/VenueDetails'
import MidSection from '../components/venue-page/MidSection';
import ReviewSection from '../components/venue-page/ReviewSection';
const Venue = () => {
let {id} = useParams()
const { venueData } = useVenues()
const filteredVenue = venueData.filter(item => {
return item.id === id
})
return(
<div>
<Header/>
<VenueDetails filteredVenue = {filteredVenue}/>
<MidSection filteredVenue = {filteredVenue}/>
<ReviewSection filteredVenue = {filteredVenue} id = {id}/>
</div>
)
}
export default Venue
Lastly, in mid section I want to pull some information out of the venue data, passed as props as filteredvenue. I'm extracting this data with the following function:
import { useEffect,useState } from 'react'
import { convertToStars } from "../../helperFunctions";
const MidSection = ({ filteredVenue }) => {
const extractRatings = () => {
const foodRatings = []
filteredVenue[0].reviews.map((rating) => {
foodRatings.push(rating.ratingFood)
})
return {foodRatings}
}
const {foodRatings} = extractRatings()
I logged out foodRatings and it returned the data I wanted. However when I refreshed the browser, the app crashed, giving the error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'reviews')
I'm assuming this is some sort of asynchronous error and that the browser is rendering this component before the data has been returned. Unsure why this is happening since I'm using async/await in the initial firebase useVenues function, and the filteredVenue object is being mapped through elsewhere in this component with no problems. Suggestions?
import { firebase } from './firebaseConfig'
problem is with firebase config you are using, when it resolve but have error

Categories

Resources