.map is not a function react, axios problem - reactjs

I am having a bit of a problem using the map function.
In the below code I am fetching NFT data through a rarible api using Axios (Works perfectly fine, I get a promise with the object as a response)
import Link from 'next/link'
import { useWeb3Context } from '../../context'
import { Web3Button } from '../../components'
import axios from 'axios'
import React, { useState } from 'react'
import NFTContainer from '#/components/NFTContainer'
const renderNotConnectedContainer = () => <Web3Button />
const fetchOwnedTokens = async (owner) => {
try {
const result = await axios.get(`https://ethereum-api.rarible.org/v0.1/nft/items/byOwner?owner=${owner}`)
return [result.data.items]
} catch (err) {
console.error(err)
return []
}
}
export const ChooseProductView = () => {
const { address } = useWeb3Context()
if (!address) {
return renderNotConnectedContainer()
} else {
const data = fetchOwnedTokens(address)
console.log(data)
return (
<div className="flex items-center justify-center">
<NFTContainer nfts={data} />
</div>
)
}
}
Then I am trying to pass the response to a container file using props, but I get an error --Unhandled Runtime Error
TypeError: nfts.map is not a function
which I think is because NFTs are not of an array datatype. Any suggestions, please? Have been stuck for a while
import React from 'react'
import NFTCard from './NFTCard'
const NFTContainer = ({ nfts }) => {
return (
<div>
{nfts.map((nft, index) => (
<NFTCard nft={nft} key={index} />
))}
</div>
)
}
export default NFTContainer

You can not use map on object so you should convert it :
<div>
{Object.keys(nfts).map((nft, index) => (
<NFTCard nft={nft} key={index} />
))}
</div>

Related

Uncaught TypeError: Cannot convert undefined or null to object

Getting error in this line as cannot convert undefined or null to abject
also i highlighted a line in which error is showing
import React from 'react';
import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { DetailsHeader, Error, Loader, RelatedSongs } from '../components';
import { useGetArtistDetailsQuery } from '../redux/sevices/shazamCore';
const ArtistDetails = () => {
const { id: artistId } = useParams();
const { activeSong, isPlaying } = useSelector((state) => state.player);
const { data: artistData, isFetching: isFetchingArtistDetails, error } = useGetArtistDetailsQuery(artistId);
if (isFetchingArtistDetails) return <Loader title="Loading artist details..." />;
if (error) return <Error />;
return (
<div className="flex flex-col">
<DetailsHeader
artistId={artistId}
artistData={artistData}
/>
<RelatedSongs
`*** data={Object.values(artistData?.songs)} //// error in this line ***`
artistId={artistId}
isPlaying={isPlaying}
activeSong={activeSong}
/>
</div>
);
};
export default ArtistDetails;
I am not sure whats the error in this
data={Object.values(artistData?.songs)}

useQuery - can not read properties of undefined

Initial query returns undefined, but all subsequent calls return valid data. If I try to map my response, an error is thrown:
can not read properties of undefined
and the whole app is down. How do i fix this?
import { useQuery } from "#apollo/client";
import { Component } from "react";
import { useState, useEffect } from "react";
import GET_PRODUCTS from '../../server/getProducts';
import './productList.sass';
class ProductList extends Component {
render() {
return (
<RenderProducts />
);
}
}
const RenderProducts = () => {
const { data } = useQuery(GET_PRODUCTS);
console.log(data.products.map(product => console.log(product)));
const products = data.products.map((product) => {
return (
<li className="productList__item">
<img className="productList__item-img" src={product.mainImage.url} alt={product.title} />
<div className="productList__item-descr">
<div className="productList__item-title">{product.title}</div>
<div className="productList__item-price">{product.price} $</div>
</div>
</li>
)
})
return <ul>{products}</ul>
}
export default ProductList;
If I try to map my response, an error is thrown:
and the whole app is down. How do i fix this?
You'll need to render something when the query is in a loading state. You can take advantage of the loading and error properties of useQuery hook. Here's a sample:
const RenderProducts = () => {
const { data, loading, error } = useQuery(GET_PRODUCTS);
if(loading) return <div>loading...</div>
if(error) return <div>cannot render products...something went wrong</div>
// if the query has finished loading products and there's no error,
// You can access data.products
// and write your logic
console.log(data.products.map(product => console.log(product)));
const products = data.products.map((product) => {
return (
<li className="productList__item">
<img className="productList__item-img" src={product.mainImage.url} alt={product.title} />
<div className="productList__item-descr">
<div className="productList__item-title">{product.title}</div>
<div className="productList__item-price">{product.price} $</div>
</div>
</li>
)
})
return <ul>{products}</ul>
}

How do I unit test an object of arrays in React Testing Library?

I have a parent component CafeList.js that makes a service call to firebase and returns cafe data as arrays within an object. I pass this entire object as props to Cafe.js where it is mapped over, and properties are destructured out and rendered (eg, the cafe name: name).
I want to write a test to check that the name element is being rendering in the Cafe.js component, but I'm not sure how to access props that are in the form of an array or object. I'm new to RTL so am a bit lost - any suggestions?
CafeList.jsx
import React, { useState,useEffect } from 'react'
import db from '../fbConfig'
import Cafe from './Cafe'
const CafeList = () => {
const [cafes,setCafe] = useState([])
useEffect(() => {
let cafeArray = []
db.collection('cafes')
.get()
.then(snapshot => {
snapshot.forEach(cafe => {
cafeArray.push(cafe)
})
setCafe(cafeArray)
})
},[])
const [...cafeData] = cafes.map((cafe) => {
const { name, photoURL } = cafe.data()
return { name:name,photoURL:photoURL, id:cafe.id}
})
return(
<div className="cafe-container-container">
<h2 className = 'main-subheading'>Reviews</h2>
<Cafe cafes = {cafeData}/>
</div>
)
}
export default CafeList
Cafe.jsx
import React from 'react'
import {Link} from 'react-router-dom'
const Cafe = ({ cafes }) => {
return (
<div className="cafe-grid">
{
cafes.map((cafe) => {
return (
<Link
to={`/cafe-reviews/${cafe.id}`}
style={{ textDecoration: "none", color: "#686262" }}
>
<div className="cafe-container">
<h3>{cafe.name}</h3>
<img src={cafe.photoURL}></img>
</div>
</Link>
)
})
}
</div>
)
}
export default Cafe
cafe.test.js
import { render, screen } from '#testing-library/react'
import Cafe from '../components/Cafe'
test('is cafe name rendering', () =>{
render(<Cafe cafe = {[]}/>)
const nameElement = screen.getByText(//the cafe name as passed by props)
expect(nameElement).toBeInTheDocument
})

Next JS & Prisma TypeError: posts.map is not a function

I'm working with Prisma in Next JS for the first timeand i've been getting this error.
I'm importing data from prisma client in my dynamic page and i'm using simple code here.
Here is my code:
import Head from 'next/head';
import { Container, Div1, Div2, Div3 ,Button , Input ,Label } from '../../components/Header/HeaderStyles';
import {useState} from 'react';
import { PrismaClient } from '#prisma/client'
const prisma = new PrismaClient()
export default function Details({posts}) {
return (
<div>
{posts.map((post) => (
<div key={post.id}>
{post.id} {post.text}
</div>
))}
</div>
)
}
export async function getServerSideProps(context) {
const { id } = context.query
const data = await prisma.contact.findFirst({
where: {
id: Number(id)
}
})
return{
props:{
posts:data,
}}
}

Component not rerendering after axios Get (React)

I'm trying to render List of items of my DB using React.Context.
All my request work pretty well.
when i console log my states first I get an empty array and then array with the data that I need but my component is not updating. I have to go to another page an then go back to this page to get the data. I don't really understand why... here are my files..
ArticlesContext.js :
import React, { useState, createContext, useEffect } from 'react';
import axios from 'axios'
export const ArticlesContext = createContext();
export function ArticlesProvider(props) {
const [articles, setArticles] = useState([]);
const [user, setUser] =useState(0)
async function getArticles () {
await axios.get(`/api/publicItem`)
.then(res => {
setArticles(res.data);
})
}
useEffect( () => {
getArticles()
}, [user])
console.log(articles);
return (
<ArticlesContext.Provider value={[articles, setArticles]}>
{props.children}
</ArticlesContext.Provider>
);
}
Inventaire.js :
import React, { useContext, useEffect, useState } from 'react';
import './Inventaire.css';
import { ArticlesContext } from '../../../context/ArticlesContext';
import DeleteAlert from './Delete/Delete';
import Modify from './Modify/Modify';
import Filter from './Filter/Filter';
import axios from 'axios'
import Crud from '../../Elements/Articles/Crud/Crud';
import List from './List/List';
export default function Inventaire() {
const [articles, setArticles] = useContext(ArticlesContext);
const [filter, setFilter] = useState(articles)
console.log(articles);
//list for Inputs
const cat = articles.map(a => a.category.toLowerCase());
const categoryFilter = ([...new Set(cat)]);
const gender = articles.map(a => a.gender.toLowerCase());
const genderFilter = ([...new Set(gender)]);
//Event Listenner
//Uncheck All checkboxes
function UncheckAll() {
const el = document.querySelectorAll("input.checkboxFilter");
console.log(el);
for (var i = 0; i < el.length; i++) {
var check = el[i];
if (!check.disabled) {
check.checked = false;
}
}
}
//SearchBar
const searchChange = (e) => {
e.preventDefault();
const stuff = articles.filter((i) => {
return i.name.toLowerCase().match(e.target.value.toLowerCase())
})
setFilter(stuff)
UncheckAll(true)
}
const Types = (e) => {
if (e.target.checked === true) {
const stuff = filter.filter((i) => {
return i.category.toLowerCase().match(e.target.value.toLowerCase())
})
setFilter(stuff)
console.log(articles);
} else if (e.target.checked === false) {
setFilter(articles)
}
}
const Gender = (e) => {
if (e.target.checked === true) {
const stuff = filter.filter((i) => {
console.log(i.category, e.target.value);
return i.gender.toLowerCase().match(e.target.value.toLowerCase())
})
setFilter(stuff)
} else if (e.target.checked === false) {
setFilter(articles)
}
}
return (
<div className="inventaireContainer">
<input type="text" placeholder="Recherche un Article" onChange={searchChange} />
<div className="inventaireMenu">
<Crud />
<Filter
filter={Types}
categorys={categoryFilter}
genre={genderFilter}
target={Gender}
/>
</div>
<List filter={filter} articles={articles}/>
</div>
)
}
List.js :
import React from 'react';
import DeleteAlert from '../Delete/Delete';
import Modify from '../Modify/Modify';
export default function List({ filter, articles }) {
return (
<div>
{filter.map((details, i) => {
return (
<div className="inventaireBlock" >
<div className="inventaireGrid">
<div className="inventaireItemImg">
<img src={details.image} alt="ItemImg" />
</div>
<h2>{details.name}</h2>
<h3>{details.category}</h3>
<h3>{details.gender}</h3>
<div>
<p>S :{details.sizes[0].s}</p>
<p>M :{details.sizes[0].m}</p>
<p>L :{details.sizes[0].l}</p>
<p>XL :{details.sizes[0].xl}</p>
</div>
<h2> Prix: {details.price}</h2>
<div className="modify">
<Modify details={details._id} />
</div>
<div className="delete" >
<DeleteAlert details={details._id} articles={articles} />
</div>
</div>
</div>
)
})}
</div>
)
}
Thanks for your time

Resources