Can't get the data from map - reactjs

Okay I should be dumb, the first console log gives me data but when I put it through map it shows undefined. I really made some digging but stuck at this stage.
import React from 'react'
const Users = ({ users } : { users:any }) => {
return (
<div>
{ console.log(users) }
{users.map(({user} : {user:any},{i} : {i:any}) => (
<div className="card">
{console.log("test: " + user)}
<div className="card-body">
<h5 className="card-title">{user.name}</h5>
<h6 className="card-subtitle mb-2 text-muted">{user.name}</h6>
</div>
</div>
))}
</div>
)
};
export default Users

TypeScript can infer the types because you have explicitly set them:
import React from 'react'
const Users = ({ users } : { users:any }) => {
return (
<div>
{ console.log(users) }
{users.map((user, i) => (
<div className="card">
{console.log("test: " + user)}
<div className="card-body">
<h5 className="card-title">{user.name}</h5>
<h6 className="card-subtitle mb-2 text-muted">{user.name}</h6>
</div>
</div>
))}
</div>
)
};
export default Users

Assuming users is an array of user objects, try this:
import React from 'react'
const Users = ({ users } : { users:any }) => {
return (
<div>
{ console.log(users) }
{users.map((user : any, i : any) => (
<div className="card">
{console.log("test: " + user)}
<div className="card-body">
<h5 className="card-title">{user.name}</h5>
<h6 className="card-subtitle mb-2 text-muted">{user.name}</h6>
</div>
</div>
))}
</div>
)
};
export default Users

Related

How to pass props to a component on clicking button?

I have displayed all the anime images from api, now I want if any anime result is clicked then it should open details for that particular anime. I have created component Details where I want to send details of anime.
how can I send details of anime to the component Details ?
Here is my code:
import { useEffect, useState } from 'react';
import './CSS/style.css';
import Details from './components/Details';
function App() {
const [user, setUser] = useState([])
const getUsers = async () =>{
const response = await fetch('https://ghibliapi.herokuapp.com/films')
setUser(await response.json());
}
useEffect(() => {
getUsers();
}, []);
const getDetail = (e) =>{
// what should I write here to pass props on component < Details />
console.log(e)
}
return (
<>
<h2>Anime World</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
{
user.map((curElem) => {
return (
<div className="col-10 col-md-4 mt-5" key={curElem.id} >
<div className="card">
<img src={curElem.image} className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<h5 className="card-title">{curElem.title} </h5>
<button onClick={getDetail} >Get Detail</button>
</div>
</div>
</div>
)
})
}
</div>
</div>
</>
);
}
export default App;
Dummy values are given to component Details right now, I have to get correct value from props.
import React from 'react';
import './details.css';
function Details() {
return (
<>
<h2>Information of Anime</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
<div className="col-10 col-md-8 mx-auto" >
<div className="card box">
<img src= '...' className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<div className='details'>
<h5><span>Title:</span> Title</h5>
<h5><span>Original Title:</span> Original Title</h5>
<h5><span>Director:</span> Director</h5>
<h5><span>Producer:</span> Producer</h5>
<h5><span>Release Date:</span> date</h5>
<h5><span>Running time:</span> time</h5>
<h5><span>Description:</span> <p> Description</p></h5>
</div>
</div>
</div>
</div>
</div>
</div>
</>
)
}
export default Details;
I'm going to assume that the list you receive from the API is the list of each anime, and when you click you want to render the selected anime using the Details component. If that's the case this is my approach
import { useEffect, useState } from 'react';
import './CSS/style.css';
import Details from './components/Details';
function App() {
const [user, setUser] = useState([]);
const [anime, setAnime] = useState(null);
const getUsers = async () =>{
const response = await fetch('https://ghibliapi.herokuapp.com/films');
setUser(await response.json());
};
useEffect(() => {
getUsers();
}, []);
const getDetail = (anime) =>{
setAnime(anime);
};
return (
<>
<h2>Anime World</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
{user.map((elem) => (
<div className="col-10 col-md-4 mt-5" key={curElem.id}>
<div className="card">
<img src={elem.image} className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<h5 className="card-title">{elem.title} </h5>
<button onClick={() => getDetail(elem)} >Get Detail</button>
</div>
</div>
</div>
))}
</div>
</div>
{anime && <Details {...anime} />}
</>
);
}
export default App;
So basically what I'm doing here is rendering <Details /> only when an anime element is in state. If it's null it won't render the component.
Secondly I'm spreading the selected element into the Details component, so that inside the component you can access each property like this:
import React from 'react';
import './details.css';
function Details(props) {
const { title } = props; // each prop is each property of the selected anime
return (
<>
<h2>Information of Anime</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
<div className="col-10 col-md-8 mx-auto" >
<div className="card box">
<img src= '...' className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<div className='details'>
<h5><span>Title:</span> {title}</h5>
<h5><span>Original Title:</span> Original Title</h5>
<h5><span>Director:</span> Director</h5>
<h5><span>Producer:</span> Producer</h5>
<h5><span>Release Date:</span> date</h5>
<h5><span>Running time:</span> time</h5>
<h5><span>Description:</span> <p> Description</p></h5>
</div>
</div>
</div>
</div>
</div>
</div>
</>
)
}
export default Details;

Sanity posts display all categories, not just ones associated with post

I am working on making a blog using React and Sanity, and I want to display the categories associated with each post underneath each post. I am able to display the categories, but it displays all categories, not just the ones associated with each specific post. How can I make it so each posts displays only the categories associated with it?
Here is my code:
import React, { useEffect, useState } from 'react'
import client from '../client'
import BlockContent from '#sanity/block-content-to-react'
import { Link } from 'react-router-dom'
function Main() {
const [posts, setPosts] = useState([])
useEffect(() => {
client.fetch(
`*[_type == "post"] {
title,
slug,
body,
author,
mainImage {
asset -> {
_id,
url
},
alt
},
publishedAt,
"categories": categories[]->title
}`
).then((data) => setPosts(data))
.catch(console.error)
}, [])
return (
<div className='grid lg:grid-cols-3 md:grid-cols-2 gap-8 m-4 '>
<div>
{posts.slice(0, 1).map((p, i) => (
<Link to = {`/blog/${p.slug.current}`} className=''>
<article key = {p.slug.current} className=''>
<img src = {p.mainImage.asset.url} alt = {p.title} className='' />
<div>
<p className='font-bold text-xl text-secondary'>{p.title}</p>
<div className=''>
<p className='text-sm'>By Brandon Pyle | {new Date(p.publishedAt).toLocaleDateString()}</p>
{posts.map((c, i) => (
<p className='inline'>{c.categories}, </p>
))}
</div>
</div>
</article>
</Link>
))}
</div>
<div className='my-[-16px]'>
{posts.slice(1, 4).map((p, i) => (
<Link to = {`/blog/${p.slug.current}`} className='col-start-2'>
<article key = {p.slug.current} className='flex my-4'>
<img src = {p.mainImage.asset.url} alt = {p.title} className='w-auto h-auto max-h-[80px]' />
<div>
<p className='font-bold text-xl text-secondary'>{p.title}</p>
<p className='text-sm'>By Brandon Pyle | {new Date(p.publishedAt).toLocaleDateString()}</p>
<div>
{posts.map((c, i) => (
<p className='inline'>{c.categories}, </p>
))}
</div>
</div>
</article>
</Link>
))}
</div>
</div>
)
}
export default Main
Thanks to #cfm I was able to find a solution:
Your query looks good. But you are mapping posts again inside the .map
of posts. I would expect you to do p.categories.map in the inner map,
if you wanted only this posts categories titles.
As he suggested, I simply switched posts.map to p.categories.map, and this fixed the problem! Here is the full fixed code:
import React, { useEffect, useState } from 'react'
import client from '../client'
import BlockContent from '#sanity/block-content-to-react'
import { Link } from 'react-router-dom'
function Main() {
const [posts, setPosts] = useState([])
useEffect(() => {
client.fetch(
`*[_type == "post"] {
title,
slug,
body,
author,
mainImage {
asset -> {
_id,
url
},
alt
},
publishedAt,
"categories": categories[]->title
}`
).then((data) => setPosts(data))
.catch(console.error)
}, [])
return (
<div className='grid lg:grid-cols-3 md:grid-cols-2 gap-8 m-4 '>
<div>
{posts.slice(0, 1).map((p, i) => (
<Link to = {`/blog/${p.slug.current}`} className=''>
<article key = {p.slug.current} className=''>
<img src = {p.mainImage.asset.url} alt = {p.title} className='' />
<div>
<p className='font-bold text-xl text-secondary'>{p.title}</p>
<div className=''>
<p className='text-sm'>By Brandon Pyle | {new Date(p.publishedAt).toLocaleDateString()}</p>
{p.categories.map((c, i) => (
<p className='inline'>{c}, </p>
))}
</div>
</div>
</article>
</Link>
))}
</div>
<div className='my-[-16px]'>
{posts.slice(1, 4).map((p, i) => (
<Link to = {`/blog/${p.slug.current}`} className='col-start-2'>
<article key = {p.slug.current} className='flex my-4'>
<img src = {p.mainImage.asset.url} alt = {p.title} className='w-auto h-auto max-h-[80px]' />
<div>
<p className='font-bold text-xl text-secondary'>{p.title}</p>
<p className='text-sm'>By Brandon Pyle | {new Date(p.publishedAt).toLocaleDateString()}</p>
<div>
{p.categories.map((c, i) => (
<p className='inline'>{c}, </p>
))}
</div>
</div>
</article>
</Link>
))}
</div>
</div>
)
}
export default Main

Cannot define properties of undefined

I am having an issue with my skillImage components.
I am not sure where the issue is coming from.
I get error message cannot read properties of undefined : id but it has been destructured correctly.
I have put below the following components involved, SkillContext, Skill, SkillsList.
The line of code in question is const { skillCard: {id, skill} } = useContext(SkillContext);
Can someone tell me what is wrong, please?
Thanks in advance
skill.js
import Image from "next/dist/client/image";
import { FaTimes, FaRegCalendarAlt, FaSchool,FaSpinner } from "react-icons/fa";
import styles from '../../styles/Home.module.scss'
//import { FaStar } from 'react-icons/fa';
import { AiFillStar , AiOutlineStar } from 'react-icons/ai'
import { useState, useContext } from 'react';
import { CourseFilterContext } from "../contexts/CourseFilterContext";
import { SkillProvider, SkillContext } from "../contexts/SkillContext";
function Course({ courseTitle, hours, level, year }) {
return (
<>
<span className={styles.course}>
<strong>Course :</strong> {courseTitle}{" "}
</span>
<span className={styles.course}>
<strong>Hours: </strong> {hours}
</span>
<span className={styles.course}>
<strong>Level :</strong> {level}
</span>
<span className={styles.course}>
<strong>Year :</strong> {year}
</span>
</>
);
}
function Courses() {
const { courseYear } = useContext(CourseFilterContext);
const { skillCard } = useContext(SkillContext);
const courses = skillCard.courses;
const level = skillCard.level;
return (
<div className={styles.courseBox, "h-250"}>
{courses
.filter(function (course) {
return course.year === courseYear;
})
.map(function (course) {
return (
<Course {...course} level={level} key={skillCard.courses.id} />
)
})
}
</div>
);
}
function SkillImage() {
const { skillCard: {id, skill} } = useContext(SkillContext);
,
return (
<div className="speaker-img d-flex flex-row justify-content-center align-items-center h-300">
<Image
src={`/images/skill-${id}.png`}
className="contain-fit"
alt={`${skill}`}
width="300"
height="300"
/>
</div>
);
}
function SkillFavorite () {
const { skillCard, updateRecord } = useContext(SkillContext);
const [inTransition, setInTransition] = useState(false);
function doneCallBack () {
setInTransition(false);
console.log(`In SkillFavorite: doneCallBack ${new Date().getMilliseconds()}`)
}
return (
<div className={styles.icon}>
<span onClick={function () {
setInTransition(true);
updateRecord(
{
...skillCard, favorite: !skillCard.favorite,
},
doneCallBack
)
}}>
{ skillCard.favorite === false ?
<AiFillStar fill="orange"/> : <AiOutlineStar fill="yellow"/>
}{" "}
Favorite{" "}
{ inTransition === true ? (
<span><FaSpinner className="fa-spin" fill="orange"/></span>
): null}
</span>
</div>
)
}
function SkillDescription() {
const { skillCard } = useContext(SkillContext);
const { skill, description, school, } = skillCard;
return (
<div>
<h3 className="text-truncate text-justify w-200">
{skill}
</h3>
<SkillFavorite />
<p className="text-justify skill-info">{description}</p>
<div className="social d-flex flex-row mt-4 justify-content-between">
<div className="school mb-2">
{/* <FaSchool className="m-3 align-middle " fill="#000"/> */}
<h5>School</h5>
<h6>{school}</h6>
</div>
<div className="calendar mb-2">
{/* <FaRegCalendarAlt className="m-3 align-middle " fill="#000"/> */}
{/* <h5>Year</h5>
<h6>{courses[0].year}</h6> */}
</div>
</div>
</div>
);
}
function SkillAction () {
return (
<div className="row mb-2">
<button
className="btn btn-primary w-100"
onClick={() => handleEditClick()}
>Edit
</button>
<div className="row mt-2">
<FaTimes className="m-3 " fill="#ffc800" onClick={() => handleDeleteClick(idx)} />
</div>
</div>
);
}
function Skill({ skillCard, updateRecord, insertRecord, deleteRecord }) {
const { showCourses } = useContext(CourseFilterContext);
return (
<SkillProvider skillCard={skillCard} updateRecord={updateRecord} insertRecord={insertRecord} deleteRecord={deleteRecord}>
<div className="col-xs-12 col-sm-12 col-md-6 col-lg-4 col-sm-12 col-xs-12">
<div className="card card-height p-4 mt-4 mb-2 h-300">
<SkillImage />
<div className="card-body">
<SkillDescription />
{showCourses === true ?
<Courses /> : null}
</div>
<div className="card-footer">
<SkillAction />
</div>
</div>
</div>
</SkillProvider>
);
}
export default Skill;
SkillsList
import Skill from "../components/Skill";
import styles from "../../styles/Home.module.scss";
import ReactPlaceholder from "react-placeholder";
import useRequestDelay, { REQUEST_STATUS} from "../hooks/useRequestDelay";
import { data } from '../../SkillData';
import { CourseFilterContext} from "../contexts/CourseFilterContext";
import { useContext } from "react";
function SkillsList () {
const {
data: skillData,
requestStatus,
error,
updateRecord,
insertRecord,
deleteRecord
} = useRequestDelay(2000, data)
const { searchQuery, courseYear } = useContext(CourseFilterContext);
if(requestStatus === REQUEST_STATUS.FAILURE) {
return(
<div className="text-danger">
Error: <b>Loading Speaker Data Failed {error}</b>
</div>
)
}
//if (isLoading === true) return <div className="mb-3">Loading...</div>
return (
<div className={styles.container, "container"}>
<ReactPlaceholder
type="media"
rows={15}
className="skillsList-placeholder"
ready={requestStatus === REQUEST_STATUS.SUCCESS}
>
<div className="row">
{skillData
.filter(function (skillCard) {
return (
skillCard.skill.toLowerCase().includes(searchQuery)
);
})
.filter(function (skillCard) {
return skillCard.courses.find((course) => {
return course.year === courseYear;
})
})
.map(function (skillCard) {
return (
<Skill
key={skillCard.id}
skillCard={skillCard}
updateRecord={updateRecord}
insertRecord={insertRecord}
deleteRecord={deleteRecord}
/>
);
})}
</div>
</ReactPlaceholder>
</div>
);
}
export default SkillsList;
SkillContext
import { createContext } from "react";
const SkillContext = createContext();
function SkillProvider({children, skillCard, updateRecord, insertRecord, deleteRecord}) {
return (
<SkillContext.Provider
value={skillCard, updateRecord, insertRecord, deleteRecord}>
{children}
</SkillContext.Provider>
)
}
export { SkillContext, SkillProvider}

Content not displayed despite present data - React

Could you tell me why my offer content is always empty ?
The "toto" is not displayed and my data are displayed because of the line "console.log(offers").
const ListProduct = (offers : any) => {
console.log(offers);
const offersDisplay = offers ? (
<div>
{ () => {
console.log("test");
offers.map((shop :any) => {
shop.offers.map((offer:any) => {
return(
<div className="card border-secondary mb-3 listMaxWidth">
<div className="card-header">{shop.name}</div>
<div className="card-body">
<img src={offer.picture} className="imgOffer"/>
<h4 className="card-title">{offer.name}</h4>
<p className="card-text">{shop.description}</p>
</div>
</div>
);
});
})
}
}
</div>
):'toto';
return(
<div>
{offersDisplay }
</div>
)
}
export default ListProduct;
I tried so many different way to write it, unfortunately can't find the right way ...
Could you help me please ?
Thanks in advance
You don't need to pass a callback function in your code
const offersDisplay = offers ? (
<div>
//this callback
{ () => {
And also you don't return from your first map.
And the last thing is that you need to include the code in your return that way it gets executed every time the offers data is changed.
You need to change your code like this
const ListProduct = (offers : any) => {
return(
<div>
{
offers && offers.length && offers.map((shop :any) => {
return shop.offers.map((offer:any) => {
return(
<div className="card border-secondary mb-3 listMaxWidth">
<div className="card-header">{shop.name}</div>
<div className="card-body">
<img src={offer.picture} className="imgOffer"/>
<h4 className="card-title">{offer.name}</h4>
<p className="card-text">{shop.description}</p>
</div>
</div>
);
});
})
}
</div>
)
}
export default ListProduct;

React Error: Cannot read property 'map' of undefined

I have been trying to resolve this error for almost 2 hours but no luck. I have even researched and used the bind method but still no luck with mapping a props that was passed through a parent component. Your help will be greatly appreciated.
import React from "react";
import { Link } from "react-router-dom";
const PostList = ({ postItem }) => {
postItem.map((post) => (
<div className="mx-auto mb-3 card w-75" key={post.id}>
<div className="card-body">
<h5 className="card-title">{post.title}</h5>
<p className="card-text">{post.comment}</p>
<Link to="/create">
<ion-icon
style={{ color: "#fc5185", fontSize: "20px" }}
name="trash-outline"
></ion-icon>
</Link>
</div>
</div>
));
};
export default PostList;
And the parent component is
class Dashboard extends Component {
state = {
posts: [
{
id: 1,
title: "Hello",
comment: "it is sunny today",
},
],
};
createPost = (title, comment) => {
const newPost = {
id: Math.floor(Math.random() * 1000),
title,
comment,
};
this.setState({
posts: [...this.state.posts, newPost],
});
};
render() {
return (
<div>
<CreatePost createPost={this.createPost} />
<PostList postItem={this.state.posts} />
</div>
);
}
}
export default Dashboard;
I guess you have missed to add return to the PostList component, you can do it in three ways (read about arrow functions)
const PostList = ({ postItem }) => postItem.map((post) => (
<div className="mx-auto mb-3 card w-75" key={post.id}>
<div className="card-body">
<h5 className="card-title">{post.title}</h5>
<p className="card-text">{post.comment}</p>
</div>
</div>
));
const PostList = ({ postItem }) => (
postItem.map((post) => (
<div className="mx-auto mb-3 card w-75" key={post.id}>
<div className="card-body">
<h5 className="card-title">{post.title}</h5>
<p className="card-text">{post.comment}</p>
</div>
</div>
));
);
const PostList = ({ postItem }) => {
return postItem.map((post) => (
<div className="mx-auto mb-3 card w-75" key={post.id}>
<div className="card-body">
<h5 className="card-title">{post.title}</h5>
<p className="card-text">{post.comment}</p>
</div>
</div>
));
}
Here is the working example

Resources