How can I define src parameter in React jsx imgage tag? I map an array and I need define src parameter depends on index of array.
import leaf1 from "../../assets/menu-clip/leafes/leaf1.png";
import leaf2 from "../../assets/menu-clip/leafes/leaf2.png";
import leaf3 from "../../assets/menu-clip/leafes/leaf3.png";
import leaf4 from "../../assets/menu-clip/leafes/leaf4.png";
import leaf5 from "../../assets/menu-clip/leafes/leaf5.png";
export default function Menu(props) {
const menuList = props.menu.menuList;
return (
<div className={styles.menuContainer}>
<ul className={styles.list}>
{menuList.map( (m,i) => (
<li className={styles.menuLi}
key={i}>
{m.name}
<img src={ **leaf + (i+1)** } // ???????
alt="menu lístok"
width="50"/>
</li>
)
)}
</ul>
</div>
)
}
You could store it in a array and reference that
like
const leafs = [leaf1,leaf2,...]
//then
src={leafs[i+1]}
import leaf1 from "../../assets/menu-clip/leafes/leaf1.png";
import leaf2 from "../../assets/menu-clip/leafes/leaf2.png";
import leaf3 from "../../assets/menu-clip/leafes/leaf3.png";
import leaf4 from "../../assets/menu-clip/leafes/leaf4.png";
import leaf5 from "../../assets/menu-clip/leafes/leaf5.png";
export default function Menu(props) {
const menuList = props.menu.menuList;
const leafArray = [leaf1, leaf2, leaf3, leaf4, leaf5];
return (
<div className={styles.menuContainer}>
<ul className={styles.list}>
{
menuList.map( (m,i) => (
<li className={styles.menuLi}
key={i}>
{m.name}
<img src={ leafArray[i] }
alt="menu lístok"
width="50"/>
</li>
))
}
</ul>
</div>
)
}
Related
Hi do you render a react elements from an array of strings using object literal to get its value? let say for example I got an array of strings and I want to mapped on it using a function that returns an object literal with predefined values, if the strings matched return the react element. Here's what i've tried but doesn't display the icons
import { useCallback, useEffect, useMemo } from "react";
import PersonIcon from "#mui/icons-material/Person"
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart'
import SecurityIcon from '#mui/icons-material/Security'
import LocalActivityIcon from '#mui/icons-material/LocalActivity'
export default function App() {
const iconNames = useMemo(()=>['PersonIcon','ShoppingCartIcon', 'SecurityIcon', 'LocalActivityIcon'],[]);
const getIcons = (icon) =>{
const icons = {
PersonIcon: <PersonIcon />,
ShoppingCartIcon: <ShoppingCartIcon />,
SecurityIcon: <SecurityIcon />,
LocalActivityIcon: <LocalActivityIcon />
}
return icons[icon];
}
const displayIcons = useCallback((arr) => {
return <ul>{arr.map((icon) => { return getIcons[icon] })}</ul>
},[])
useEffect(()=>{
displayIcons(iconNames)
})
return (
<div className="App">
<h1>Icons</h1>
{displayIcons}
</div>
);
}
Assuming that the icons are imported and static, perhaps the icons object could be defined outside of the component, so that even without useMemo or useCallback, it would not be re-created when the component re-renders.
The getIcons might not be necessary to access the icons in the object, as in the output JSX, the icons[name] can be wrapped in a curly braces {} to render the icon.
Example (live demo on: stackblitz):
import PersonIcon from '#mui/icons-material/Person';
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart';
import SecurityIcon from '#mui/icons-material/Security';
import LocalActivityIcon from '#mui/icons-material/LocalActivity';
// 👇 Can be defined here if the icons are imported and static
const icons = {
PersonIcon: <PersonIcon />,
ShoppingCartIcon: <ShoppingCartIcon />,
SecurityIcon: <SecurityIcon />,
LocalActivityIcon: <LocalActivityIcon />,
};
// 👇 Just an array of the icon names for testing
const iconNames = Object.keys(icons);
export default function App() {
return (
<div className="App">
<h1>Icons</h1>
<ul>
{iconNames.map((name, index) => (
<li key={index}>{icons[name]}</li>
))}
</ul>
</div>
);
}
However depending on the use case, perhaps also consider to use other approaches instead of accessing it from an object to display a list of icons.
The example below displays a list of icons, and could also pass the MUI props to style it if needed (may not work for other libraries).
Example (live demo on: stackblitz):
// Works for MUI icons but might not for other libraries
const icons = [PersonIcon, ShoppingCartIcon, SecurityIcon, LocalActivityIcon];
export default function App() {
return (
<div className="App">
<h1>Icons</h1>
<ul>
{icons.map((Icon, index) => (
<li key={index}>
<Icon fontSize="large" color="primary" />
</li>
))}
</ul>
</div>
);
}
Just another possible approach that also works (with MUI) and accepts props for the icons, by defining the icon as component inside map:
Example (live demo on: stackblitz):
// Works for MUI icons but might not for other libraries
const icons = { PersonIcon, ShoppingCartIcon, SecurityIcon, LocalActivityIcon };
const iconNames = Object.keys(icons);
export default function App() {
return (
<div className="App">
<h1>Icons</h1>
<ul>
{iconNames.map((icon, index) => {
const Icon = icons[icon];
return (
<li key={index}>
<Icon fontSize="large" color="primary" />
</li>
);
})}
</ul>
</div>
);
}
You are calling displayIcons as a variable while this is a function.
getIcons is a function not an array. You should do getIcons(icon)
Your code can be reduce to this
import { useCallback, useEffect, useMemo } from "react";
import PersonIcon from "#mui/icons-material/Person"
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart'
import SecurityIcon from '#mui/icons-material/Security'
import LocalActivityIcon from '#mui/icons-material/LocalActivity'
export default function App() {
const iconNames = ['PersonIcon','ShoppingCartIcon', 'SecurityIcon', 'LocalActivityIcon']
const getIcons = (icon) => {
const icons = {
PersonIcon: <PersonIcon />,
ShoppingCartIcon: <ShoppingCartIcon />,
SecurityIcon: <SecurityIcon />,
LocalActivityIcon: <LocalActivityIcon />
}
return icons[icon];
}
const displayIcons = useCallback(() => {
return (
<ul>{iconNames.map((icon) => { return getIcons(icon) })}</ul>
)
},[iconNames])
return (
<div className="App">
<h1>Icons</h1>
{displayIcons()}
</div>
);
}
how to display Img array all image in react js
data***
import im1 from "../Image/10007.jpg"
export const Data =[
{
name:"aminur",
Img:[im1,im1,im1]
}
]enter code here
code :
import React from 'react'
import "./Content.css"
import { Data } from './data'
const Content = () => {
return (
<div className='content'>
{Data.map((item)=>{
return(
<div className='text'>
<img src={item.Img[0]} alt="" />
</div>
)
})}
</div>
)
}
export default Content
What I understood from your question is how to display all the images under Img array which is inside an another array of objects.
import React from 'react'
import "./Content.css"
import { Data } from './data'
const Content = () => {
return (
<div className='content'>
{Data.map((item)=>{
return(
<div className='text'>
{item?.Img.map(image=>(
<img src={image} alt="" />
))}
</div>
)
})}
</div>
)
}
export default Content
I just want to show toggled item. But all map items showing up. Basically this is the result I'm getting from onclick. I think i need to give index or id to each item but i don't know how to do it. i gave id to each question didn't work.
App.js.
import "./App.css";
import React, { useState, useEffect } from "react";
import bg from "./images/bg-pattern-desktop.svg";
import bg1 from "./images/illustration-box-desktop.svg";
import bg2 from "./images/illustration-woman-online-desktop.svg";
import { data } from "./data";
import Faq from "./Faq";
function App() {
const [db, setDb] = useState(data);
const [toggle, setToggle] = useState(false);
useEffect(() => {
console.log(db);
}, []);
return (
<>
<div className="container">
<div className="container-md">
<div className="faq">
<img src={bg} className="bg" />
<img src={bg1} className="bg1" />
<img src={bg2} className="bg2" />
<div className="card">
<h1>FAQ</h1>
<div className="info">
{db.map((dat) => (
<Faq
toggle={toggle}
setToggle={setToggle}
title={dat.title}
desc={dat.desc}
key={dat.id}
id={dat.id}
/>
))}
</div>
</div>
</div>
</div>
</div>
</>
);
}
export default App;
(map coming from simple data.js file that I created. it includes just id title desc.)
Faq.js
import React from "react";
import arrow from "./images/icon-arrow-down.svg";
const Faq = ({ toggle, setToggle, title, desc, id }) => {
return (
<>
{" "}
<div className="question" onClick={() => setToggle(!toggle)}>
<p>{title}</p>
<img src={arrow} className={toggle ? "ikon aktif" : "ikon"} />
</div>
<p className="answer border">{toggle ? <>{desc}</> : ""}</p>
</>
);
};
export default Faq;
You need to store the index value of the toggle item.
You can modify the code with only 2 lines with the existing codebase.
import "./App.css";
import React, { useState, useEffect } from "react";
import bg from "./images/bg-pattern-desktop.svg";
import bg1 from "./images/illustration-box-desktop.svg";
import bg2 from "./images/illustration-woman-online-desktop.svg";
import { data } from "./data";
import Faq from "./Faq";
function App() {
const [db, setDb] = useState(data);
const [toggle, setToggle] = useState(-1); //Modify Here
useEffect(() => {
console.log(db);
}, []);
return (
<>
<div className="container">
<div className="container-md">
<div className="faq">
<img src={bg} className="bg" />
<img src={bg1} className="bg1" />
<img src={bg2} className="bg2" />
<div className="card">
<h1>FAQ</h1>
<div className="info">
{db.map((dat, index) => ( //Modify Here
<Faq
toggle={index === toggle} //Modify Here
setToggle={() => setToggle(index)} //Modify Here
title={dat.title}
desc={dat.desc}
key={dat.id}
id={dat.id}
/>
))}
</div>
</div>
</div>
</div>
</div>
</>
);
}
export default App;
import React from "react";
import arrow from "./images/icon-arrow-down.svg";
const Faq = ({ toggle, setToggle, title, desc, id }) => {
return (
<>
{" "}
<div className="question" onClick={setToggle}>
<p>{title}</p>
<img src={arrow} className={toggle ? "ikon aktif" : "ikon"} />
</div>
<p className="answer border">{toggle ? <>{desc}</> : ""}</p>
</>
);
};
export default Faq;
You will need state for each toggle. Here is a minimal verifiable example. Run the code below and click ⭕️ to toggle an item open. Click ❌ to close it.
function App({ faq = [] }) {
const [toggles, setToggles] = React.useState({})
const getToggle = key =>
Boolean(toggles[key])
const setToggle = key => event =>
setToggles({...toggles, [key]: !getToggle(key) })
return faq.map((props, key) =>
<Faq key={key} {...props} open={getToggle(key)} toggle={setToggle(key)} />
)
}
function Faq({ question, answer, open, toggle }) {
return <div>
<p>
{question}
<button onClick={toggle} children={open ? "❌" : "⭕️"} />
</p>
{open && <p>{answer}</p>}
</div>
}
const faq = [
{question: "hello", answer: "world"},
{question: "eat", answer: "vegetables"}
]
ReactDOM.render(<App faq={faq} />, document.querySelector("#app"))
p { border: 1px solid gray; padding: 0.5rem; }
p ~ p { margin-top: -1rem; }
button { float: right; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Instead of doing this (in App component):
const [db, setDb] = useState(data);
const [toggle, setToggle] = useState(false);
you can write an useState hook like below to combine the two hooks and assign an isOpened property for each Faq element:
const [db, setDb] = useState(data.map(value=>{return {...value, isOpened:false}}));
and then right here you can do this (as the child of <div className="info">):
{db.map((dat, index) => (
<Faq
toggle={dat.isOpened}
setToggle={() => toggleById(dat.id)}
title={dat.title}
desc={dat.desc}
key={dat.id}
id={dat.id}
/>
))}
Also you need to declare toggleById function in App component:
const toggleById = (id) => {
const newDb = db.map(dat=>{
if(dat.id==id){
return {...dat,isOpened:!dat.isOpened}
}
return dat;
});
setDb(newDb);
}
and since setToggle prop of Faq, calls toggleById by its defined parameter, there is no need to do this in Faq component:
<div className="question" onClick={() => setToggle(!toggle)}>
you can simply write:
<div className="question" onClick={setToggle}>
As will be shown below when passing properties from a parent component to a child component my code is executed first before the properties arrive and when trying to do a .map of an Array it returns the error "Cannot read properties of undefined (reading 'map')". Why does this happen?
As you can see in the image, first you get undefined values which generates the error in the .map and then you get the properties
Parent component:
import React, {useEffect, useState} from "react";
import ItemDetail from "./itemDetail";
import '../../App.css';
import { useParams } from "react-router-dom";
//Component Class
const ItemDetailContainer = () => {
const [producto, productos] = useState([]);
const { productId } = useParams();
useEffect(() => {
fetch('http://localhost:3000/productos/' + productId)
.then(res=>res.json())
.then(data=>productos(data))
}, [productId]);
console.log(producto);
return (
<div className="container">
<ItemDetail
nombre={producto.nombre}
id={producto.id}
precio={producto.precio}
category={producto.category}
imagenes={producto.imagenes}
ancho={producto.ancho}
alto={producto.alto} />
</div>
)
}
export default ItemDetailContainer;
Child component:
import React from 'react';
import { Card } from 'react-bootstrap';
import ItemCount from '../itemCount';
const ItemDetail = ({ nombre, id, precio, category, imagenes, ancho, alto }) => {
console.log(imagenes);
return (
<div className="row" key={id} id={id}>
<div className="col-md-6" id="productImage">
<div className="carousel-item">
{imagenes.map((p) => (
<img src={p} className="d-block w-100" alt={nombre} />
))}
</div>
</div>
<div className="col-md-6 producto">
<div className="card">
<Card.Body>
<Card.Title>{nombre}</Card.Title>
<Card.Text>{category}</Card.Text>
<Card.Text>${precio}</Card.Text>
<ItemCount />
</Card.Body>
</div>
</div>
</div>
);
};
export default ItemDetail;
Change your code to only execute if imagenes is an array. Personally I would rethink how you are structuring your initial state. Instead of it being an empty array, perhaps make it an object with all of those properties having default values.
<div className="carousel-item">
{ Array.isArray(imagenes) && imagenes.map((p) => (
<img src={p} className="d-block w-100" alt={nombre} />
))}
</div>
I have a component that I'm currently trying to render. I put a return statement but I am still displaying an error.
import React, { useState } from 'react';
import moment from 'moment';
import {FaSpaceShuttle} from 'react-icons/fa';
export const TaskDate = ({ setTaskDate, showTaskDate, setShowTaskDate }) => {
return (
showTaskDate && (
<div className="task-date" data-testid="task-date-overlay">
<ul className="task-date__list">
<li>
<div
onClick={() => {
setShowTaskDate(false);
setTaskDate(moment().format('DD/MM/YYYY'));
}}
>
<span>
<FaSpaceShuttle />
</span>
<span>Today</span>
</div>
</li>
</ul>
</div>
)
);
};
Any help would be appreciated!
The problem is that when showTaskDate is undefined you don't render anything, you simply return undefined.
You can change your return to use conditionals and return null to render nothing if there is no showTaskDate set.
export const TaskDate = ({ setTaskDate, showTaskDate, setShowTaskDate }) => {
return (
showTaskDate ? (
<div className="task-date" data-testid="task-date-overlay">
<ul className="task-date__list">
...
</ul>
</div>
) : null
);
};