I am working with AntDesign and want to use a onLoad or a componentDidMount function. Both don't work.
How can I make a function with the same purpose?
//Things I have tried and didn't work for me. (I might be doing things wrong.)
return (
<div onLoad={() => {console.log('Toeter!')}}>
//Blah blah
</div>
)
window.onload = () => {
//Blah blah
}
componentDidMount = () => {
//Blah blah
}
What I want to do is trigger a function when the components comes on screen. The funtion is supposed to find a product in an array of objects.
EDIT:
A complete component as asked in the comments
import * as React from "react";
import {Row, Col, Image, Card, Space, Breadcrumb, Descriptions, InputNumber, Button} from 'antd';
import * as FreddieGras from "../images/freddieGras.jpg";
import "react-multi-carousel/lib/styles.css";
import {RouterProps} from "./router.props";
import {Link} from "#reach/router"
interface ProductDetailProps extends RouterProps {
id?: string;
}
export default function ProductDetail(props: ProductDetailProps) {
// Different kinds of grass
let grassKinds = [
{
name: 'Kate',
id: 1,
imageName: FreddieGras,
desc: "Lorem Ipsum dolor sit amet.",
available: true,
softness: 7,
realness: 6,
price: 17.95
},
{
name: 'Fred',
id: 2,
imageName: FreddieGras,
desc: "Lorem Ipsum dolor sit amet.",
available: false,
softness: 7,
realness: 6,
price: 17.95
},
{
name: 'Gideon',
id: 3,
imageName: FreddieGras,
desc: "Lorem Ipsum dolor sit amet.",
available: true,
softness: 7,
realness: 6,
price: 17.95
},
{
name: 'Isa',
id: 4,
imageName: FreddieGras,
desc: "Lorem Ipsum dolor sit amet.",
available: true,
softness: 7,
realness: 6,
price: 17.95
},
];
let product = {};
window.onload = () => {
product = grassKinds.find(x => x.id);
console.log('Toeter!');
}
return (
<div onLoad={() => {
console.log('Toeter!')
}}>
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
</Breadcrumb.Item>
</Breadcrumb>
<Row>
<Col span={10} justify={'space-around'} align={'center'}>
<Image
src={FreddieGras}
/>
</Col>
<Col span={14}>
<Descriptions title="User Info" style={{width: '50%'}}>
<Descriptions.Item label="Naam">Kate</Descriptions.Item>
<Descriptions.Item label="Zachtheid">7/10</Descriptions.Item>
<Descriptions.Item label="Echtheid">6/10</Descriptions.Item>
<Descriptions.Item label="Prijs /m2">€17,95</Descriptions.Item>
</Descriptions>
<Card title="Bereken oppervlakte" style={{margin: '5px'}}>
<label>Lengte (m)</label>
<InputNumber
defaultValue={1000}
formatter={value => `€ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
onChange={() => {
console.log('Number')
}}
/>
<div>
<p><b>Omtrek </b> 10 M</p>
<p><b>Oppervlakte </b> 2,5 M2</p>
</div>
</Card>
<Card title="Totaalprijs" style={{margin: '5px'}}>
<b>€ 17,95</b>
<Button onClick={() => {
console.log('In winkelwagen')
}}>In winkelwagen</Button>
</Card>
</Col>
</Row>
</div>
)
}
React components don't use window.onload and componentDidMount is reserved for and valid only in class-based components. Functional components can use an useEffect React hook with empty dependency array to have the equivalent to componentDidMount lifecycle method.
let product = {};
useEffect(() => {
product = grassKinds.find(x => x.id);
console.log('Toeter!');
}, []);
Related
i am building a restaurant website in which i have an array of all the items in their menu, looks like this -
const CardData = [
{
index: 1,
imagesrc: "require(./assets/menu/nonveg)",
title: "Tandoori Chicken",
group: "non-veg",
discprice: 400,
price: 450,
},
{
index: 2,
imagesrc: "require(./assets/menu/nonveg)",
title: "Momos Steamed",
group: "veg",
discprice: 80,
price: 100,
},
{
index: 3,
imagesrc: "require(./assets/menu/nonveg)",
title: "Non-Veg Momos Fried",
group: "non-veg",
discprice: 100,
price: 150,
}]
In a parent component i have different child "menu" components. In each menu component i want to render a different category of data.
The parent component looks like-
import React, { useState } from "react";
import CardMenu from "./CardMenu";
const Menu = () => {
return (
<div className="group">
<h1>Our Collection</h1>
<CardMenu/>
<CardMenu/>
<CardMenu/>
</div>
);
};
export default Menu;
and the child component looks like -
'''
import Tag from "./Tag";
import { useState } from "react";
const CardMenu = ({ menudata }) => {
return (
<>
<div className="menu">
<Tag />
<div className="scroll-menu">
{
menudata.map((curElem) => {
const { index, title, group, imagesrc, price, disprice } = curElem;
return (
<>
<div className="card" key={index}>
<div className="card-upper">
<div className="card-image">
<img
src={require("../assets/Duggarhutz/nonveg/nonvegfriedmomos.jpeg")}
alt=""
/>
</div>
<div className="card-info">{index}</div>
</div>
<div className="card-mid">
<div className="card-title">{title}</div>
<div className="card-icons"></div>
<div className="card-desc">
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Aliquam, vero. Provident nesciunt magni aliquid omnis eveniet
architecto optio reprehenderit at itaque aut?
</div>
</div>
<div className="card-bottom">
<div className="card-price">${price}</div>
<div className="card-descprice">${disprice}</div>
<div className="card-button">
<button>Order</button>
</div>
</div>
</div>
</>
)
})
}
</div>
</div>
</>
)
};
export default CardMenu;
---for each group i want to render a new Cardmenu with cards related to it.---
Pass in the cardData to your cardMenu like this <CardMenu cardData />
Or <CardMenu cardData=cardData />
As you are destructuring the props in CardMenu with a property menudata you need to pass a property with the same name as this:
const Menu = () => {
return (
<div className="group">
<h1>Our Collection</h1>
<CardMenu menudata={CardData}/>
</div>
);
};
i write your solution and give a suggestion to this situation:
solution- filter data from js methods:
const data = [
{
categoryName: "Banking",
categoryId: "B1",
description: "Financial sector"
},
{
categoryName: "Retail",
categoryId: "R1",
description: "Retail and customer experience"
}
];
function groupByProperty(arrayOfObjects, property) {
return arrayOfObjects.reduce((acc, curr) => {
const key = curr[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(curr);
return acc;
}, {});
}
const dataByCategoryName = groupByProperty(data, "categoryName");
console.log(dataByCategoryName);
/* Output
{
Banking: [{
categoryId: "B1",
categoryName: "Banking",
description: "Financial sector"
}],
Retail: [{
categoryId: "R1",
categoryName: "Retail",
description: "Retail and customer experience"
}]
}
*/
suggestion- you can write a search bar and filter cards by client search (realtime filtering).
you can use my sample:
enter link description here
Since you are already mapping the data inside the CardMenu component, you should:
Import CardData from the corresponding file (I suppose it is in the same directory, so probably:
import CardData from "./CardData";
Remove the extra calls to CardMenu:
<div className="group">
<h1>Our Collection</h1>
<CardMenu />
</div>
Pass CardData as a prop menudata to CardMenu:
<CardMenu menudata={CardData} />
The final code of Menu would look something like this:
import React, { useState } from "react";
import CardMenu from "./CardMenu";
import CardData from "./CardData";
const Menu = () => {
return (
<div className="group">
<h1>Our Collection</h1>
<CardMenu menudata={CardData} />
</div>
);
};
export default Menu;
Sorry this question might be duplicated, but none of the existing answers helped me
I'm a beginner in React and js
I want to add multiple objects inside the component
Like:
src={url}
name={text}
subTitle={subtext}
my index.js
const tableColumns = [
{
title: 'Title/Artist',
dataIndex: 'name',
key: 'name',
render: (text) => (
<div className="d-flex align-items-center">
<AvatarStatus
shape="square"
src="https://i.scdn.co/image/ab67616d00001e02bd26ede1ae69327010d49946"
name={text}
subTitle="Dua Lipa"
/>
</div>
),
},
];
return (
<>
<Table
className="no-border-last"
columns={tableColumns}
dataSource={recentReleasesData}
rowKey='id'
pagination={false}
/>
</>
my data.js
export const RecentReleasesData = [
{
id: '#5332',
artwork: 'https://i.scdn.co/image/ab67616d00001e02bd26ede1ae69327010d49946',
name: 'Future Nostalgia',
artist: 'Dua Lipa',
label: 'Warner Records',
barcode: '19029500',
releasedate: '2021-02-11',
tracks: '11',
promolink: 'Smart Link',
status: 'Approved',
},
{
id: '#6438',
artwork: 'https://i.scdn.co/image/ab67616d00001e02caf82abb2338880577e472be',
name: 'Love',
artist: 'Someonw',
label: 'UMG Records',
barcode: '50029500',
releasedate: '2017-08-21',
tracks: '2',
promolink: 'Smart Link',
status: 'Rejected',
},
];
My comp AvatarStatus.js
import React from 'react';
import PropTypes from 'prop-types'
import { Avatar } from 'antd';
const renderAvatar = props => {
return <Avatar {...props} className={`ant-avatar-${props.type}`}>{props.text}
</Avatar>;
}
export const AvatarStatus = props => {
const { name, suffix, subTitle, id, type, src, icon, size, shape, gap, text,
onNameClick } = props
return (
<div className="avatar-status d-flex align-items-center">
{renderAvatar({icon, src, type, size, shape, gap, text })}
<div className="ml-2">
<div>
{
onNameClick ?
<div
onClick={() => onNameClick({name, subTitle, src, id})}
className="avatar-status-name clickable">{name}
</div>
:
<div className="avatar-status-name"><a href="javascript:void(0)">
{name}</a>
</div>
}
<span>{suffix}</span>
</div>
<div className="text-muted avatar-status-subtitle">{subTitle}</div>
</div>
</div>
)
}
AvatarStatus.propTypes = {
name: PropTypes.string,
src: PropTypes.string,
type: PropTypes.string,
onNameClick: PropTypes.func
}
export default AvatarStatus;
https://reactjs.org/docs/components-and-props.html
components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.
This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions.
codepen example
I found the solution
index.js
render: (_, record) => (
<Flex>
<AvatarStatus
shape="square"
size={50}
src={record.artwork}
name={record.title}
subTitle={record.artist}/>
</Flex>
),
I am creating a user interface for a watch. In this UI if I select a watch of particular color it must be shown in the product preview. But when I select Color of the watch it is giving me error as
TypeError: Cannot read property 'imageUrl' of undefined.
Can anyone tell me why it is happening. I am giving you code for reference.
//App.js
import logo from './logo.svg';
import React, { Component } from 'react';
import classes from './App.module.css';
import ProductPreview from './ProductPreview/ProductPreview';
import ProductDetails from './ProductDetails/ProductDetails';
import TopBar from './TopBar/TopBar';
import ProductData from './utils/ProductData';
class App extends Component {
state = {
productData : ProductData,
currentPreviewImage : "https://imgur.com/Mplj1YR.png",
showHeartBeatSection: true,
}
onColorOptionClick = (pos) => {
const updatedPreviewImage = this.state.productData.colorOptions[pos].imageUrl;
console.log(updatedPreviewImage);
this.setState({currentPreviewImage : updatedPreviewImage});
}
render() {
return (
<div className="App">
<header className="App-header">
<TopBar />
</header>
<div className={classes.MainContainer}>
<div className={classes.ProductPreview}>
<ProductPreview currentPreviewImage={this.state.currentPreviewImage} showHeartBeatSection={this.state.showHeartBeatSection} />
</div>
<div className={classes.ProductData}>
<ProductDetails data={this.state.productData} onColorOptionClick={this.onColorOptionClick} />
</div>
</div>
</div>
);
}
}
export default App;
//ProductData.js
const ProductData = {
title: 'FitBit 19 - The Smartest Watch',
description: 'Lorem ipsum dolor Lorem ipsum dolor Lorem ipsum dolor Lorem ipsum dolor Lorem ipsum dolor Lorem ipsum dolor.',
colorOptions: [
{
styleName: 'Black Strap',
imageUrl: 'https://imgur.com/iOeUBV7.png'
},
{
styleName: 'Red Strap',
imageUrl: 'https://imgur.com/PTgQlim.png'
},
{
styleName: 'Blue Strap',
imageUrl: 'https://imgur.com/Mplj1YR.png'
},
{
styleName: 'Purple Strap',
imageUrl: 'https://imgur.com/xSIK4M8.png'
},
],
featureList: [
"Time", "Heart Rate"
]
}
Object.freeze(ProductData); //This line of code just makes your object as a constant. No values can be updated.
export default ProductData;
//ProductDetails.js
import React from 'react';
import classes from './ProductDetails.module.css';
const ProductDetails = (props) => {
const colorOptions = props.data.colorOptions.map((item, pos) => {
const classArr = [classes.ProductImage];
if(pos === 0) {
classArr.push(classes.selectedProductImage);
}
return(
<img key={pos} className={classArr.join(' ')} src={item.imageUrl} alt={item.styleName} onClick={() => props.onColorOptionClick()} />
);
})
const featureList = props.data.featureList.map((item, pos) => {
const classArr = [classes.FeatureItem];
if(pos === 0){
classArr.push(classes.SelectedFeatureItem);
}
return(
<button key={pos} className={classArr.join(' ')}>{item}</button>
)
})
return(
<div className = {classes.ProductData}>
<h1 className={classes.ProductTitle}>{props.data.title}</h1>
<p className={classes.ProductDescription}>{props.data.description}</p>
<h3 className={classes.SectionHeading}>Select Color</h3>
<div>
{colorOptions}
</div>
<h3 className={classes.SectionHeading}>Features</h3>
<div> {featureList}</div>
<button className={classes.PrimaryButton}>Buy Now</button>
</div>
);
}
export default ProductDetails;
Image of the UI :
After selecting watch of the color:
You forgot pass pos when call props.onColorOptionClick. Just update like this:
onClick={() => props.onColorOptionClick(pos)} />
You are not passing position value on the click function to props.onColorOptionClick in ProductDetails.js .
<img key={pos} className={classArr.join(' ')} src={item.imageUrl} alt={item.styleName} onClick={() => props.onColorOptionClick(pos)} />
This should work for you.
I recently watch a tutorial on YouTube about making Tabs using React and I got these codes.
App.js
import './App.css';
import { Tab } from './components/Tab/Tab';
const tabContent = [
{
title: "Chennai",
content: "Chennai is the capital of the Indian state." },
{
title: "Lorem Ipsum",
content: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Exercitationem."
},
{
title: "Dolor sit amet",
content: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eius, veniam!"
}];
function App() {
return (
<>
<div className="row">
<div className="col">
<div className="row text-left">
<Tab active={1}>
{ tabContent.map((tab, idx) =>
<Tab.TabPanel key={`Tab-${idx}`} tab={tab.title}>
{tab.content}
</Tab.TabPanel>) }
</Tab>
</div>
</div>
</div>
</>
);
}
export default App;
Tab.js
import React, { useState, useEffect } from 'react'
import './Tab.css'
export const Tab = ({children, active=0}) => {
const [activeTab, setActiveTab] = useState(active);
const [tabsData, setTabsData] = useState([]);
useEffect(() => {
let data = [];
React.Children.forEach(children, element => {
if(!React.isValidElement(element)) return; //exit the function
const {props: {tab, children}} = element;
data.push({tab, children})
})
setTabsData(data);
}, [children])
return (
<div className="w-100 custom-tab">
<ul className="nav nav-tabs">
{
tabsData.map(({tab}, idx) => (
<li className="nav-item">
<a
className = {`nav-link ${idx === activeTab ? "active" : ""}`}
href = "#"
onClick={() => setActiveTab(idx)}
>
{tab}
</a>
</li>
))
}
</ul>
<div className="tab-content p-3">
{tabsData[activeTab] && tabsData[activeTab].children}
</div>
</div>
)
}
const TabPanel = ({children}) => {
return {children}
}
Tab.TabPanel = TabPanel;
When I look to App.js I see there's a custom element named Tab.TabPanel. I think that is the children of the Tab element. And then I look to Tab.js and I see that there's TabPanel const that runs a function to return it's children.
I wonder, what is the purpose of Tab.TabPanel here? What will he render? And should I make codes like this in the future?
It's not the children, it's more of a namespace. The library author didn't want to export both Tab and TabPanel and decided to attach TabPanel to the function that is exported (for whatever reason). It's an opinionated choice that makes it harder to tree shake but just understand that Tab.TabPanel is just another React component.
The author could have just as easily done
export Tab = () => {...};
export TabPanel = () => {...};
and you could have consumed it as
import {Tab, TabPanel} from "./Tab.jsx";
const Foo = () => (
<div>
<TabPanel>
<Tab/>
<Tab/>
</TabPanel>
</div>
);
or however you wanted to use it.
This is my data (in a seperate JS file):
const someData= [
{
id: 1,
title: "Article 1",
desc: "Some description lorem ipsum",
},
{
id: 2,
title: "Article 2",
desc: "Some description lorem ipsum",
},
{
id: 3,
title: "Article 3",
desc: "Some description lorem ipsum",
}
]
export default someData;
Now I'm mapping the data like this:
- Articles.js file
const articleItems = this.state.someData.map(item =>
<ArticleItem key={item.id} item={item}
/>)
return(
<div>{articleItems}</div>
)
And listing all articles with only the article title displayed in ArticleItem component.
- articleItem.js file
return(
<h1>{props.item.title}</h1>
)
How can I create so you can click on an article title in the list, which would then go to that specific article (url should be /article/id) and display all data for that specific article?
Use React Routers Version 4 to achiever this.
Article.js file-
const articleItems = this.state.someData.map(item =>
<Route key={item.id} path=`/${item.title}/${item.id}` render={
<ArticleItem
{...props}
item={item}
/>
} />
/>)
return(
<div>{articleItems}</div>
)
In the file where you are rendering the Links render like this.
render() {
return(
<Link to=`/${item.title}/${item.id}`>{item.title}</Link>
);
}
Don't forget to import Route and Link.
Hope this helps.