How to get value from an object of maps from Firestore - javascript

I want to access each map and their fields induvidually to pass it to a card
I tried the following code
import React, { useEffect, useState } from "react";
import Sidebar from "./Sidebar";
import Navbar from "./Navbar";
import MyStyledCard from "./RequestCard";
import CardList from "./RequestCard";
import { getDoc, doc } from "firebase/firestore";
import { db } from "../firebase";
export default function Requests() {
const [Data, setData] = useState([]);
const reg_no = "G2062059";
let list = [];
useEffect(() => {
const fetchData = async () => {
const docRef = doc(db, "meta", "project-ideas");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("Document data:", docSnap.data());
setData(docSnap.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
};
// Data.map((anObjectMapped, index) => {
// console.log(anObjectMapped.name);
// });
fetchData();
}, []);
return (
<div className="requests_out">
<div className="requsts_side">
<Sidebar />
</div>
<div className="requests_main">
<Navbar />
<div className="widgets">
<h2>{Data[reg_no]}</h2>
</div>
</div>
</div>
);
}
It gives an error like this.
Uncaught Error: Objects are not valid as a React child (found: object with keys {grp_id, pTitle, status, pDescription}). If you meant to render a collection of children, use an array instead.
If i give console.log(Data) it gives an object like this
.

The fetch is correct, however you are trying to render a javascript object. This is not possible and invalid JSX.
Choose what property inside G2062059 you want to display
Invalid code:
<div className="widgets">
<h2>{Data[reg_no]}</h2> <--- THIS IS INVALID JSX
</div>
Valid code:
Render a property of an object (string)
<div className="widgets">
<h2>{Data[reg_no]?.status}</h2>
</div>

Related

Objects are not valid as a React child (found: [object HTMLDivElement]). If you meant to render a collection of children, use an array instead. :(

I'm getting an error( react-dom.development.js:14887 Uncaught Error: Objects are not valid as a React child (found: [object HTMLDivElement] and react_devtools_backend.js:4026 The above error occurred in the component:). If you meant to render a collection of children, use an array instead.) when I want to add needCard as a child in a Modal, this is just for practice so I have kept everything inside App.tsx. My class looks like this:
import React, {useState, useEffect} from "react";
import "./App.css";
import SocialCard from "./SocialCard/SocialCard";
import Modal from './Modal/Modal';
import {keyable} from "./Location/Location";
function App() {
const [allUsers, setAllUsers] = useState([]);
const [users, setUsers] = useState([]);
const [needCard, setNeedCard] = useState(<div></div>)
useEffect(() => {
(async () => {
let userData;
try {
const response = await fetch("https://randomuser.me/api/?results=10");
userData = await response.json();
} catch (error) {
console.log(error);
userData = [];
}
setAllUsers(userData.results);
setUsers(userData.results);
})();
}, []);
const filterCards = event => {
const value = event.target.value.toLowerCase();
const filteredUsers = allUsers.filter(user => (`${user.name.first} ${user.name.last}`.toLowerCase().includes(value)));
setUsers(filteredUsers);
}
const getCard = (e) => {
setModalActive(true)
setNeedCard(e.target.closest('.card'))
}
console.log(needCard);
const [modalActive, setModalActive] = useState(false)
function getCards(arr:Array<keyable>) {
return arr.map((user, index) =>
(
<SocialCard key={index} userData={user} getCard={getCard}/>
))
}
return (
<div className="App">
<h1>Social Cards</h1>
<input className="search-box" onInput={filterCards} placeholder="Search..."/>
<div className="cards-container">
{getCards(users)}
</div>
<Modal active={modalActive} setActive={setModalActive}>
{needCard}
</Modal>
</div>
);
}
export default App;

React: How to avoid duplication in a state array

I am making MERN social media app.
I want to show all the friends of the current user in a list in SideBar.jsx .
Home.jsx (parent of Sidebar.jsx)
import React, { Component } from "react";
import { Person } from "#material-ui/icons";
import Topbar from "../../components/topbar/Topbar";
import Sidebar from "../../components/sidebar/Sidebar";
import Feed from "../../components/feed/Feed";
import Rightbar from "../../components/rightbar/Rightbar";
import "./home.css";
export default function Home() {
return (
<>
<Topbar />
<div className="homeContainer">
<Sidebar />
<Feed />
<Rightbar />
</div>
</>
);
}
SideBar.jsx
import "./sidebar.css";
import React, { Component, useContext, useState } from "react";
...
import { axiosInstance } from "../../config";
export default function Sidebar() {
const { user } = useContext(AuthContext);
const [followings, setFollowings] = useState([]);
const followingsList = user.followings;
useEffect(() => {
const fetchFollowings = async () => {
followingsList.map(async (id) => {
try {
const theUser = await axiosInstance.get(`/users?userId=${id}`);
if (followings.includes(theUser.data)) {
} else {
setFollowings((prev) => [...prev, theUser.data]);
}
} catch (error) {
console.log(error);
}
});
};
fetchFollowings();
}, [user]);
return (
<div className="sidebar">
.....
<ul className="sidebarFriendList">
{followings.map((u) => (
<CloseFriend key={u._id} user={u} />
))}
</ul>
</div>
</div>
);
}
For example, in this case, in the state "followings", there are 2 user objects.
So, the line
followings.map((u) => (...
should only show 2 entries.
However, the result is below.
As you can see, it is showing each friend twice.
I tired to check if a user object already exists in followings by doing
if (followings.includes(theUser.data)) {
} else {
setFollowings((prev) => [...prev, theUser.data]);
}
But this is not working.
How can I make sure that it only shows each user once?
I want it to be like this
Any help would be greatly appreciated. thank you
This is happening because it seems that your useEffect method is being fired two times (probably because you are using React.StrictMode) and you are setting the state inside the .map method (that is not good because you trigger a new render each time you call the setState).
What I would recommend you to do, is to remove the setState from the .map method and just set the new state after you format your data. So it would be something like this:
const newFollowings = followingsList.map(async (id) => {
try {
const theUser = await axiosInstance.get(`/users?userId=${id}`);
return theUser.data;
} catch (error) {
console.log(error);
}
});
setFollowings(newFollowings);
Probably you would have to add a filtering to the array in case there are some errors (because on errors the mapped value would be undefined):
.filter(data => data);
When you are using the .map function with async/await Promise.all usually always does the trick. Instead of pushing the state on every iteration you collect the followers list and set the state when all your fetching is done. I did not test it yet, but I hope it works.
const followingsList = user.followings;
useEffect(() => {
const fetchFollowings = async () => {
const list = await Promise.all(followingsList.map(async (id) => (
await axios.get('/user?userId=' + id);
)));
setFollowers(list);
};
fetchFollowings();
}, [user]);
Note: let me know if it works, if not I'll do a little sandbox on my own

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([]).

Error : Object are not valid as a react child

I am Trying to loop through the data coming from database, but react is giving me this error
i have tried by rendering the list in seperate componet still it doesnot work!,i am beginner to react ecosystem.
fetched data look like-
and my page code is this-
import React, { useEffect, useState } from 'react';
import './account.scss';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { selectCurrentUser } from '../../reducer/user/user.selectors';
import Order from '../../models/order';
const AccountPage = ({ currentUser }) =>{
const[orders,setOrders]=useState([]);
useEffect(()=>{
const fetchFunc= async () =>{
try{
const response= await fetch(`https://orders-6exxx.firebaseio.com/userorders/${currentUser.id}.json`);
if(!response.ok){
throw new Error('Something Went Wrong!');
}
const resData= await response.json();
const loadedOrders=[];
for(const key in resData){
loadedOrders.push(
new Order(
key,
resData[key].cartItems,
resData[key].totalAmount,
new Date(resData[key].date)
));
}
setOrders(loadedOrders);
}catch(err){
throw err;
}
};
fetchFunc();
},[currentUser]);
console.log(orders);
return(
<div className='account'>
{orders&&orders.length ? (
<div className='account__container'>
{
orders.map(order =>(
<div className='account__containers__orders'>
<div className='account__containers__orders--date'>
{order.date}
</div>
{
order.items.map(item => (
<div className='account__containers__orders__item'>
<div>{item.name}</div>
<div>{item.quantity} x</div>
<div>{item.price}</div>
</div>
))
}
<div className='account__containers__orders--total'>
<span className='price--tag'>₹</span> {order.totalAmount}
</div>
</div>
))
}
</div>
) : (
<div className='orders-loading'>
No Orders
</div>
)}
</div>
);
};
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser
});
export default connect(
mapStateToProps
)(AccountPage);
single data is loading but when i try to print multiple data, it gives me this error
You store new Date() inside your orders state and it is treated ot be an object. In order to render it you can convert it to a string
{order.date.toString()}
or
{order.date.toDateString()}

Uncaught (in promise) TypeError: Cannot read property 'fisierUrl' of undefined

I create a react app and i want to fetch data (images urls)from my API.
in Detali .js i wrote this code:
Detalii.js
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import url from "../url";
import Header from "../components/Header";
const Detalii = () => {
const [info, setInfo] = useState({});
const { id } = useParams();
useEffect(() => {
async function getData() {
try {
const res = await fetch(`${url}/detalii/${id}`);
const data = await res.json();
setInfo(data);
} catch (error) {
console.log(error);
}
}
getData();
}, [id]);
//console.log(info);
return (
<div className="bg-detalii">
<Header info={info} />
</div>
);
};
export default Detalii;
in Header conponent i display image like this:
Header.js:
import React from "react";
const Header = ({ info }) => {
console.log(info);
return (
<div className="header">
<img src={info.fisier.fisierUrl} className="img-detalii" alt="poza" />
<p className="text-detalii">{info.nume}</p>
</div>
);
};
export default Header;
in my console info.fisier object is like this:
in Detali.js it shows me the error when it displays image.how to fix it? thanks
look at the src={info.fisier.fisierUrl} especially at info.fisier.fisierUrl.
At the beginning your request is in progress and your info is equal to {}.
So it's {}.fisier.fisierUrl. {}.fisier is undefined. And undefined.fisierUrl throws an error
How to fix:
Instead of src={info.fisier.fisierUrl} try src={info && info.fisier && info.fisier.fisierUrl}
I believe the issue is that you try to render <Header /> before the fetch call has returned and setInfo has been called.
One solution could be to render Header only when info is "truthy". I.e.
return (
<div className="bg-detalii">
{info && (<Header info={info} />)}
</div>
);

Categories

Resources