React: object throws ".keys is not a function Error" - javascript

I'm aware that this error may be quite common and have been answered several times before, but I couldn't find a solution.
My code always throws this error: ".map is not a function". I know that this happens because data is not an array. So I tried to solve this with .keys function but this throws the ".keys is not a function" error. I'm declaring const data in the parent component and want to use it in the child component.
I think my error depends on a false use of .keys. But after much Googling I'm still not one step further.
This is my Child-Code:
import React from "react";
import Card from 'react-bootstrap/Card';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import Container from 'react-bootstrap/Container';
import {Link} from 'react-router-dom'
const PostsRow = (data) => {
{return (
<Container>
<Row>
{data.keys(data).map((data) => {
console.log(data + "is mount")
return (
<Col className="col-6 col-md-6 col-lg-3 card">
<Link to={data.url}>
<Card className=" text-center ">
<Card.Img variant="top" src={data.imagesrc} />
<Card.Body>
<Card.Title>{data.title}</Card.Title>
</Card.Body>
</Card>
</Link>
</Col>
);
})}
</Row>
</Container>
);
};
export default PostsRow;
This is home.jsx (parent):
import React from "react";
import './route.css';
import PostsRow from "../components/Content/PostsRow";
const Home = () => {
const data = {
title: "Ersti",
imagesrc: "./490.jpg",
url: "/meineposts"
};
return (
<div>
<PostsRow data={data}/>
</div>
);
};
export default Home;
This is working fine as long as const data is declared in the PostsRow.jsx, but when I try to declare it in Home.jsx and use props the above error throws.

As data is an object. To get its keys, you should write: Object.keys(data).
And, you have a typo in props destructuring : it should be ({data}).
Your example data is simply an object, not an array, so you don't need to use map or Object.keys here, you can simply write:
<Col className="col-6 col-md-6 col-lg-3 card">
<Link to={data.url}>
<Card className="text-center">
<Card.Img variant="top" src={data.imagesrc} />
<Card.Body>
<Card.Title>{data.title}</Card.Title>
</Card.Body>
</Card>
</Link>
</Col>

PostsRow will be called with props and data is property of it. so you have to use it like
const PostsRow = ({data}) => {
And you've to convert your data to array like
const data = [{
title: "Ersti",
imagesrc: "./490.jpg",
url: "/meineposts"
}];

Related

how i get querySelectorAll html elements in react?

I am using react with functional component. I also use react-bootstrap , I attached the react-bootstrap carousel , everything is fine with react-bootstrap, for some functionality, I want to get three divs in react , divs has same classes. I know if I use simple html css js then I easily do that,
querySelectorAll(".indicator-btn")
but i want this on react. How can I do that? please suggest me a best practices for that.
This is a my component , in the last i have three divs which i want for Dom.
import React, { useState } from "react";
import Cardcarousel from "./Cardcarousel";
import { Carousel } from "react-bootstrap";
import Brand1img from "../images/brand1.png";
import Airbnbimg from "../images/Airbnb.png";
import Microsoft from "../images/microsoft.png";
import { Row, Col } from "react-bootstrap";
function Carouselx() {
const [index, setIndex] = useState(0);
const handleSelect = (selectedIndex, e) => {
console.log(selectedIndex, "e=>", e);
setIndex(selectedIndex);
};
const isSlide = (slide) => {
console.log("slide no => " + slide);
console.log(this);
};
return (
<>
<div className="px-5 py-3">
<Carousel activeIndex={index} onSelect={handleSelect} onSlide={isSlide}>
<Carousel.Item>
<Row>
<Col>
<Cardcarousel
name="Technology UI/UX"
companylogo={Brand1img}
type="Full time job"
/>
</Col>
<Col>
<Cardcarousel
name="Technology Backend developer"
companylogo={Airbnbimg}
type="Part time job"
/>
</Col>
<Col>
<Cardcarousel
name="Technology Backend developer"
companylogo={Microsoft}
type="Internee"
/>
</Col>
</Row>
</Carousel.Item>
<Carousel.Item>
<Row>
<Col>
<Cardcarousel
name="Technology UI/UX"
companylogo={Brand1img}
type="Full time job"
/>
</Col>
<Col>
<Cardcarousel
name="Technology Backend developer"
companylogo={Airbnbimg}
type="Part time job"
/>
</Col>
<Col>
<Cardcarousel
name="Technology front end developer"
companylogo={Microsoft}
type="Internee"
/>
</Col>
</Row>
</Carousel.Item>
</Carousel>
<div className="carusel-indecator-container">
<div className="indicator-btn indicator-btn1"></div>
<div className="indicator-btn indicator-btn2"></div>
<div className="indicator-btn indicator-btn3"></div>
</div>
</div>
</>
);
}
export default Carouselx;
You could use useState to get its refs (also useRef but there'll be a lot more inconveniences potentially).
const [btn1, setBtn1] = useState();
const [btn2, setBtn2] = useState();
const [btn3, setBtn3] = useState();
...
<div ref={setBtn1} className="indicator-btn indicator-btn1"></div>
<div ref={setBtn2} className="indicator-btn indicator-btn2"></div>
<div ref={setBtn3} className="indicator-btn indicator-btn3"></div>
At some point (after 1st rendering) you'll have btn1, btn2, btn3 as button elements. If you want to use it, assumingly imperatively, you could useEffect
useEffect(() => {
if (!btn1 || !btn2 || !btn3) return;
// do something with these refs i.e. make them jquery! $(btn1)
}, [btn1, btn2, btn3]);

properties.map is not a function when map

I'm getting the error "TypeError: properties.map is not a function", however when i console.log(properties) i can see the data. Can anyone explain me what i'm doing wrong?
If i remove the map code obviously the error is not showing. Is it because "properties" is not defined yet during the render? I'm a bit confused of why it's not defined since as i said i can see the data on load with the console.
import React, { Component } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { AndroidOutlined, AppleOutlined } from '#ant-design/icons';
import Tabs, { TabPane } from '#iso/components/uielements/tabs';
import Select, { SelectOption } from '#iso/components/uielements/select';
import Button from '#iso/components/uielements/button';
import PageHeader from '#iso/components/utility/pageHeader';
import Box from '#iso/components/utility/box';
import { Form, Input, Checkbox, Col, Row } from 'antd'
import LayoutWrapper from '#iso/components/utility/layoutWrapper.js';
import ContentHolder from '#iso/components/utility/contentHolder';
import IntlMessages from '#iso/components/utility/intlMessages';
import FormGeneral from './FormGeneral';
import FormDetails from './FormDetails';
import propertiesActions from '#iso/redux/properties/actions';
const Option = SelectOption;
const {
loadFromApi,
} = propertiesActions;
export default function PropertiesPage() {
const dispatch = useDispatch();
React.useEffect(() => {
dispatch(loadFromApi());
}, [dispatch]);
const { properties, property, isLoading } = useSelector(
state => state.Properties
);
const rowStyle = {
width: '100%',
display: 'flex',
flexFlow: 'row wrap',
};
const colStyle = {
marginBottom: '16px',
};
const gutter = 16;
// Show data
console.log(properties);
console.log(isLoading);
return (
<LayoutWrapper>
<PageHeader>Properties</PageHeader>
<Box>
<Tabs defaultActiveKey="1">
<TabPane
tab={
<span>
<AppleOutlined />
General
</span>
}
key="1"
>
<div>
{console.log(properties)}
{properties.map(e =>
<div key={e.id}>
{e.id}
</div>
)}
</div>
<Row style={rowStyle} gutter={gutter} justify="start">
<Col md={12} sm={12} xs={24} style={colStyle}>
<Box>
<FormGeneral />
</Box>
</Col>
</Row>
</TabPane>
<TabPane
tab={
<span>
<AndroidOutlined />
Tab 2
</span>
}
key="2"
>
<FormDetails />
</TabPane>
</Tabs>
</Box>
</LayoutWrapper>
);
}
UPDATED:
properties is empty object at first
What if you try properties?.map, so it doesn't map if it is undefined, and wait until you really get the array. Because I don't have a big knowledge about redux, but from what I can read from your code, I understand that you are getting the properties asynchronously.
By default properties is undefined. .map cannot work with undefined. Try to use:
const { properties = [], property, isLoading } = useSelector(
state => state.Properties
);
It is possible to extend the answer and change the initialState, but your reducer code is needed.
before you map properties you should check if it is undefined because the initial value of state object in react is undefined and I think that if you will roll up in your console you should see an undefined print to the console
<div>
{console.log(properties)}
{properties !== undefined ? properties.map(e =>
<div key={e.id}>
{e.id}
</div>
): null}
</div>
In fact the object was defined but empty, i had to check for the length
<div>
{console.log(properties)}
{properties.length > 1 ? properties.map(e =>
<div key={e.id}>
{e.id}
</div>
): null}
</div>
Doing this resolved the issue.

Cannot read properties of undefined (reading 'map') in React

I'm trying to make a ecommerce site using the commerce.js library. I have already 8 products in the library API. I have a Products.js component where I'm passing those array of product objects I got from App.js and again passing single product object to the Product.js component. To do this, I'm using mapping function to pass each object as props to the Product.js component. And I'm receiving this error. I tried commenting out the mapping block and only console logged the products variable from App.js and the prop products in Products.js, there I'm getting all the 8 products so no problem in there. But I don't get it why I'm getting this error in the mapping function.
App.js
import React, { useState, useEffect } from "react";
import { commerce } from "./lib/commerce";
import { Products, Navbar } from "./components";
function App() {
const [products, setProducts] = useState([]);
const fetchProduct = async () => {
const data = await commerce.products.list();
setProducts(data);
};
useEffect(() => {
fetchProduct();
}, []);
console.log("products", products);
return (
<div className="App">
<Navbar />
<Products products={products} />
</div>
);
}
export default App;
Products.js
import React from "react";
import { Grid } from "#material-ui/core";
import Product from "./Product/Product";
import useStyles from "./style";
const Products = ({ products }) => {
const classes = useStyles();
return (
<main className={classes.content}>
<div className={classes.toolbar} />
<Grid container justifyContent="center" spacing={4}>
{products.data.map((product) => (
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product} />
</Grid>
))}
</Grid>
</main>
);
};
export default Products;
Product.js
import React from "react";
import {
Card,
CardMedia,
CardContent,
CardActions,
Typography,
IconButton,
} from "#material-ui/core";
import { AddShoppingCart } from "#material-ui/icons";
import useStyles from "./styles";
const Product = ({ product }) => {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardMedia
className={classes.media}
image={product.media.source}
title={product.name}
/>
<CardContent>
<div className={classes.cardContent}>
<Typography variant="h5" gutterBottom>
{product.name}
</Typography>
<Typography variant="h5">
{product.price.formatted_with_symbol}
</Typography>
</div>
<Typography
variant="body2"
dangerouslySetInnerHTML={{ __html: product.description }}
/>
</CardContent>
<CardActions disableSpacing className={classes.cardActions}>
<IconButton aria-label="Add to Cart">
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
);
};
export default Product;
In your App.js change your fetchProduct function as follows:
const fetchProduct = async = {
const products = await commerce.products.list();
setProducts(products.data);
}
and then in your Products.js map over the products instead of products.data,
{products.map((product) => (
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product} />
</Grid>
))}
EXPLANATION:
The initial State of products is an empty array, which is passed down to the products component, where you tried products.data.map() but products is an array (initially) and there is no data property on arrays, so it threw error.
There are several ways you can get around this, but if you are only using the products data from the response then you can go with the above approach, where you map over the products not products.data and setProducts() with the products array instead of products object.
Do you can to attached screen with error?
I think, you try to read data before is are loading, you can prevent this by add something like this (products.data || []).map for example.. or change default state in App.js on useState({data:[]})

× TypeError: Cannot read property 'image' of undefined

I am currently developing an e-commerce site I'm very new in this area I caught up with this error when ı want to import some images to my pages
Here is My productscreen.js
import React from "react";
import { Link } from "react-router-dom";
import { Row, Col, Image, ListGroup, Button, Card } from "react-bootstrap";
import Rating from "../components/Rating";
import products from "../products";
function ProductScreen({ match }) {
const product = products.find((p) => p._id === match.params._id)
return (
<div>
<Link to="/" className="btn btn-light my-3">
Go Back
</Link>
<Row>
<Col md={6}> if (!product) {
<Image src={product.image} alt={product.name} fluid />
}
</Col>
Thats my error message
add a null check condition in code
<Image src={product && product.image} alt={product && product.name} fluid />
console log product before returning and check if it's getting the data or not
hope by this you will get the idea what's wrong
You cannot use if conditions in the jsx syntax. Change like this:
<Col md={6}> {product && <Image src={product.image} alt={product.name} fluid />}
</Col>
I fix my problem const code should be this way in my solution.
function ProductScreen({ match }) {
const product = products.find((p) => p._id === match.params.id)
I have to delete my _ in _id thanks for the helps.

Image URL not accessible in an API Call

I'm trying to access an image URL in an API call in my react project but, the error message I'm getting is that the URL not defined as an error. Have tried to find the error but couldn't find it. Kindly assist in helping me to know what I'm doing wrong.
Below is my code. The place giving me a problem is commented out.
import React, { Component } from 'react'
import axios from "axios";
import { Card} from "react-bootstrap";
export default class App extends Component {
state = {
data: []
};
componentDidMount() {
this.fetchCountryData();
}
fetchCountryData = async () => {
const url = "https://api.thecatapi.com/v1/breeds";
try {
const response = await axios.get(url);
const data = await response.data;
this.setState({
data
});
} catch (error) {
console.log(error);
}
};
render() {
return (
<div className="App">
<h1>React Component Life Cycle</h1>
<h1>Calling API</h1>
<div>
{
this.state.data.map((item, id) => (
<div key={id}>
{console.log(item)}
<Card style={{ width: '18rem' }}>
{/* <Card.Img variant="top" src={item.image.url} /> This part is giving me the problem */}
<Card.Body>
<Card.Title>{item.name}</Card.Title>
<Card.Text>
{item.origin}
</Card.Text>
<Card.Text>
{item.temperament}
</Card.Text>
<Card.Text>
{item.weight.metric}
</Card.Text>
<Card.Text>
{item.description}
</Card.Text>
{/* <Button variant="primary">Go somewhere</Button> */}
</Card.Body>
</Card>
{/* { <img src={item.image.url} alt=""/> } Please why is this not working ? */}
{/* {item.name} <br/>
{item.origin} <br/>
{item.temperament} <br/>
{item.life_span} <br/>
{item.weight.metric} <br/>
{item.description} <br/> */}
</div>
))
}
</div>
</div>
)
}
}
This is interesting. My first thought was that when the component renders, item.image object does not exist so that's why you cannot access a property in an undefined object. But then I realized it doesn't throw for item.weight.metric. I will be waiting to see what other people have to say about this.
However, the basic fix is you can simply use image link as item.image && item.image.url or shortly item.image?.url so it doesn't throw.

Categories

Resources