React JS. How can I display the image inside the object? - javascript

How can I display the image inside the object in React.js?
const Area = () =>{
const flags = [
{ id: 1, name: "USA", image: "./us.png" },
{ id: 2, name: "Canada", image: "./ca.png" },
];
return (
<div>
{flags.map((area) => {
return <img key={area.id} src={area.image} />;
})}
</div>
)}

The very first thing that you need to do is wrap the src in {} which you're doing already.
Then if you're using webpack. Instead of : <img src={"./us.png"} />
You need to use require() like this <img src={require('./us.png')} />
const Area = () => {
const flags = [
{ id: 1, name: "USA", image: "./us.png" },
{ id: 2, name: "Canada", image: "./ca.png" },
]
return (
<div>
{flags.map((area) => {
return <img key={area.id} src={require(area.image)} />;
})}
</div>
)}
}
Another option would be to first import the image as shown below
import ca from './us.png' or const us = require('./us.png).
Then add them to your flags object like shown below:
import usa from './us.png;
import canada from './ca.png;
const Area = () => {
const flags = [
{ id: 1, name: "USA", image: usa },
{ id: 2, name: "Canada", image: canada },
]
return (
<div>
{flags.map((area) => {
return <img key={area.id} src={area.image} />;
})}
</div>
)}
}

You can use require for images inside an object.But your code works fine even without that you just have to return it inside return method().
const Area = () =>{
const flags = [
{ id: 1, name: "USA", image: require('./us.png') },
{ id: 2, name: "Canada", image: require('./ca.png') },
]
return (
<div>
{flags.map((area) =>
<img key={area.id} src={area.image} />
)}
</div>
)
}
return(
Area()
)
It works fine this way as well
const Area = () =>{
const flags = [
{ id: 1, name: "USA", image: "./us.png" },
{ id: 2, name: "Canada", image: "./ca.png" },
]
return (
<div>
{flags.map((area) =>
<img key={area.id} src={area.image} />
)}
</div>
)
}
return(
Area()
)

As I mentioned in my comments that please double check the path of the image. Image path might be a problem else it is looking fine. Moreover, you can press ctrl+click on path to route to that folder or check it manually.

Related

How to use drag and drop in ant design?

What I want is an example about how to make the drag and drop of my Table that works properly, but I cannot figure out how to make it works in (functional components)
My code :
function Preview() {
const { name } = useParams();
const [fieldsOfForm, setFieldsOfForm] = useState([]);
const [selectedForm, setSelectedForm] = useState([]);
const columns = [
{
title: 'Posição',
dataIndex: 'pos',
width: 30,
className: 'drag-visible',
render: () =>
<MenuOutlined style={{ cursor: 'grab', color: '#999' }}/>
},
{
title: "Form Name",
dataIndex: "field",
key: "field",
render: (text) => <a>{text}</a>,
},
{
title: "Tipo",
dataIndex: "fieldtype",
key: "fieldtype",
},
];
useEffect(() => {
let mounted = true;
let loadingStates = loading;
if (mounted) {
setFieldsOfForm(location.state);
loadingStates.allFields = false;
setLoading(false);
}
return () => (mounted = false);
}, [selectedForm]);
return (
//Some jsx....
<Row gutter={1}>
<Col span={1}></Col>
<Table dataSource={fieldsOfForm}
columns= {columns}/>
</Row>
// More jsx...
);
}
export default Preview;
Everything that I found on internet about this drag and drop from the lib of antd is in class component , but I wanted to make it works in my functional one.
Example that I found :
multi row drag-able table (antd)
I want some example in function component if someone has tried it already and could help me ?
Here's a functional working example:
import React from "react";
import "antd/dist/antd.css";
import { Table } from "antd";
import {
sortableContainer,
sortableElement,
sortableHandle
} from "react-sortable-hoc";
import { MenuOutlined } from "#ant-design/icons";
const data = [
{
key: "1",
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park",
index: 0
},
{
key: "2",
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park",
index: 1
},
{
key: "3",
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 2
},
{
key: "4",
name: "4",
age: 32,
address: "New York No. 1 Lake Park",
index: 3
},
{
key: "5",
name: "5",
age: 42,
address: "London No. 1 Lake Park",
index: 4
},
{
key: "6",
name: "6",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 5
}
];
const DragHandle = sortableHandle(({ active }) => (
<MenuOutlined style={{ cursor: "grab", color: active ? "blue" : "#999" }} />
));
const SortableItem = sortableElement((props) => <tr {...props} />);
const SortableContainer = sortableContainer((props) => <tbody {...props} />);
function SortableTable() {
const [dataSource, setDataSource] = React.useState(data);
const [selectedItems, setSelectedItems] = React.useState([]);
const getColumns = () => {
return [
{
title: "Sort",
dataIndex: "",
width: 30,
className: "drag-visible",
render: (d, dd, i) => (
<>
<DragHandle active={selectedItems.includes(i)} />
</>
)
},
{
title: "Name",
dataIndex: "name",
className: "drag-visible"
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
};
const merge = (a, b, i = 0) => {
let aa = [...a];
return [...a.slice(0, i), ...b, ...aa.slice(i, aa.length)];
};
const onSortEnd = ({ oldIndex, newIndex }) => {
let tempDataSource = dataSource;
if (oldIndex !== newIndex) {
if (!selectedItems.length) {
let movingItem = tempDataSource[oldIndex];
tempDataSource.splice(oldIndex, 1);
tempDataSource = merge(tempDataSource, [movingItem], newIndex);
} else {
let filteredItems = [];
selectedItems.forEach((d) => {
filteredItems.push(tempDataSource[d]);
});
let newData = [];
tempDataSource.forEach((d, i) => {
if (!selectedItems.includes(i)) {
newData.push(d);
}
});
tempDataSource = [...newData];
tempDataSource = merge(tempDataSource, filteredItems, newIndex);
}
setDataSource(tempDataSource);
setSelectedItems([]);
}
};
const DraggableContainer = (props) => (
<SortableContainer
useDragHandle
disableAutoscroll
helperClass="row-dragging"
onSortEnd={onSortEnd}
{...props}
/>
);
const DraggableBodyRow = ({ className, style, ...restProps }) => {
// function findIndex base on Table rowKey props and should always be a right array index
const index = dataSource.findIndex(
(x) => x.index === restProps["data-row-key"]
);
return (
<SortableItem
index={index}
{...restProps}
selected={selectedItems.length}
onClick={(e) => {
if (e.ctrlKey || e.metaKey) {
selectedItems.includes(index)
? selectedItems.splice(selectedItems.indexOf(index), 1)
: selectedItems.push(index);
setSelectedItems(selectedItems);
} else {
setSelectedItems([]);
}
}}
/>
);
};
return (
<>
<h3>"CNTRL + Click" to select multiple items</h3>
<Table
pagination={false}
dataSource={dataSource}
columns={getColumns()}
rowKey="index"
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow
}
}}
/>
{selectedItems.length ? <>{selectedItems.length} items selected </> : ""}
</>
);
}
You can play with it in Sandbox

Loops inside react components leading to rendering of sub components

I have a data as below
myArr = [
{
"Sl.No": "n1",
company: "ABC",
Name: "Sam",
Designation: "Architect",
Salary: "100",
},
{
"Sl.No": "n2",
company: "ABC",
Name: "Bill",
Designation: "Engineer",
Salary: "200",
},
{
"Sl.No": "n3",
company: "ABC",
Name: "Jill",
Designation: "HR",
Salary: "300",
},
{
"Sl.No": "n4",
company: "XYZ",
Name: "Bill",
Designation: "Engineer",
Salary: "250",
},
{
"Sl.No": "n5",
company: "XYZ",
Name: "Tom",
Designation: "Mechanic",
Salary: "150",
},
{
"Sl.No": "n6",
company: "LMN",
Name: "Tom",
Designation: "Mechanic",
Salary: "150",
},
];
I want to create a react app which shows the data as below. Nothing but listing the employees & their designations under the name of the company.
The boxes on the right are number of doses of vaccine taken (data comes from somewhere else)
I have the components set-up like so
Inside App.js
I have left out importing the components , css & all that for simplcity
export const App = () => {
return (
<div className=app}>
<CompanyInfo />
</div>
);
}
Inside CompanyInfo.js
export const CompanyInfo= () => {
let companies= [...new Set(myArr.map((item) => item.company))];
const renderingComponents = (company: string, index: number) => {
return (
<Fragment key={index}>
<p className="company-name">{company}</p>
<div className="category-employees">
<CompanyEmployee toggled={toggled} />
</div>
;
</Fragment>
);
};
return (
<div className=company-info}>
{companies.map((item, index) => renderingComponents(item, index))}
</div>
);
}
So far, so good, I can render the titles of all the companies & I have hardcoded the CompanyEmployee to see if it populates within every company & it does. However, I want CompanyEmployee to be dynamic & I am not able to figure our how to pass the company related info to the components (that data will have info of all the company employees) and then map the CompanyEmployee component on that data.
Inside CompanyEmployee.js
Please note that this is like a wrapper for 2 components
export const CompanyEmployee= () => {
return (
<div className=ce}>
<EmployeePrimaryDetails />
<EmployeeVacDetails />
</div>
);
}
Inside EmployeePrimaryDetails.js
export const EmployeePrimaryDetails= (props) => {
return (
<div className=epd>
<span className="name">{props.Name}</span>
<span className="designation">{props.Designation}</span>
</div>
);
}
Can anyone guide me on how I render EmployeePrimaryDetails.js for each employee of the company?
I tried to do a for of, forEach, map in the renderingComponents function of CompanyInfo itself but when I try that I get the Typescript error "Expression Expected" (I am using typescript with React in my project).
Any help is appreciated.
Inside renderingComponents function you can say:
const filteredList = myArr.filter(employee => employee.company === company);
filteredList.map(employee => (<CompanyEmployee employee={employee} toggled={toggled} />));
Resulting in this:
const renderingComponents = (company: string, index: number) => {
const filteredList = myArr.filter(employee => employee.company === company);
return (
<Fragment key={index}>
<p className="company-name">{company}</p>
<div className="category-employees">
{filteredList.map(employee => (<CompanyEmployee employee={employee} toggled={toggled} />))}
</div>
;
</Fragment>
);
};
So in CompanyEmployee component you can destructure the data you need.

Data object with array of different groups, trying to display ordered by group type using .map() and pushing to new array nothing is rendering

I have a React Component I'm building out that accepts a data object as props.
This data object holds an array of groups each with it's own group type.
What I'm trying to do is map over each group in the array and display it's contents as it's own section, but I also want to ensure that all of the objects with the type grid display together, followed by any sections with a list type no matter what position they are in the array.
So even if the array holds the values like:
[{Grid}, {List}, {Grid}, {List}, {Grid}]
It will display like this:
Group #1 (Grid)
Contents
Group #2 (Grid)
Contents
Group #3 (Grid)
Contents
Group #4 (List)
Contents
Group #5 (List)
Contents
The problem I'm having is that I wrote two separate components to handle the styling of each type and then passed them into a function that creates a new array from the original to then render, and nothing is displaying. I'm not getting any error messages or anything in the console so I'm completely stumped as to where I'm going wrong.
Here are my components, the data structure and a Codesandbox:
// Component File
import "./styles.css";
import data from "./resourceMock";
import FileIcon from "./FileIcon";
const GridView = (group) => {
const { groupName, items } = group;
return (
<>
<h2>{groupName}</h2>
<ul
style={{
display: "inline-flex",
flexWrap: "wrap",
listStyleType: "none"
}}
>
{items.map((item) => {
return (
<li style={{ height: "40vh", flexGrow: 1 }}>
<img src={item.img} style={{ height: "150px", width: "150px" }} />
<h4>{item.name}</h4>
<h5>{item.subtitle}</h5>
</li>
);
})}
</ul>
</>
);
};
const ListView = (group) => {
const { groupName, items } = group;
return (
<>
<h2>{groupName}</h2>
<ul style={{ listStyleType: "none" }}>
{items.map((item) => {
return (
<li>
<FileIcon />
{item.title}
</li>
);
})}
</ul>
</>
);
};
function renderList(group) {
const lists = [];
if (!group) return null;
data.map((group) => {
switch (group.groupType) {
case "grid":
return lists.push((group) => {
<GridView group={group} />;
});
case "list":
return lists.push((group) => {
<ListView group={group} />;
});
default:
return lists.push((group) => {
<ListView group={group} />;
});
}
});
return lists;
}
export default function App() {
return <div className="App">{data.map((group) => renderList(group))}</div>;
}
Data Structure:
export default [
{
groupName: "Marvel Characters",
groupType: "grid",
items: [
{
name: "Iron Man",
subtitle: "Inventor Tony Stark",
img:
"https://www.denofgeek.com/wp-content/uploads/2019/02/mcu-1-iron-man.jpg?resize=768%2C432"
},
{
name: "Incredible Hulk",
subtitle: "Bruce Banner",
img:
"https://lh3.googleusercontent.com/proxy/-jHnFcGLqlxjdOl9Mf99UPBk4XJKcQ1Hsv7lPYEs8Vai874sW0l5TUwn3acriwGpE36aUDPpZHPFzccRUt7b7POGOWCFIbgYomTO9bDCXF0eovxFGdr_D3P-0wfLnkUMOOJDG09MgAzqSCbiDq-A"
}
]
},
{
groupName: "Magic Cards",
groupType: "list",
items: [
{
title: "Kamahl, Fist Of Krosa",
link:
"https://gatherer.wizards.com/pages/card/Details.aspx?multiverseid=220490"
},
{
title: "Seedborn Muse",
link:
"https://gatherer.wizards.com/pages/card/Details.aspx?multiverseid=446180"
}
]
},
{
groupName: "DC Characters",
groupType: "grid",
items: [
{
name: "Batman",
subtitle: "Bruce Wayne",
img:
"https://static.wikia.nocookie.net/marvel_dc/images/a/a6/Batman_Vol_2_2_Variant_Textless.jpg/revision/latest/top-crop/width/360/height/450?cb=20120228075313"
},
{
name: "Martian Manhunter",
subtitle: "J'onn J'onzz",
img:
"https://cdn.flickeringmyth.com/wp-content/uploads/2021/03/Martian-Manhunter-600x338.png"
}
]
},
{
groupName: "Kaiju and Mechs",
groupType: "grid",
items: [
{
name: "Godzilla",
img:
"https://www.denofgeek.com/wp-content/uploads/2019/05/godzillakingofmonsters-2.jpg?resize=768%2C432"
},
{
name: "Hunter Vertigo",
img: "https://i.ytimg.com/vi/7F-iZYAqSbw/maxresdefault.jpg"
}
]
},
{
groupName: "Comic Books",
groupType: "list",
items: [
{
title: "Descender",
link: "https://imagecomics.com/comics/series/descender"
},
{
title: "East of West",
link: "https://imagecomics.com/comics/series/east-of-west"
},
{
title: "Letter 44",
link: "https://onipress.com/collections/letter-44"
}
]
}
];
I have fixed the issues.
Sandbox: https://codesandbox.io/s/affectionate-sinoussi-5suro
You are already looping over data inside renderList, so we can directly have <div className="App">{renderList(data)}</div>;
To sort, we can use Array.sort()
data.sort((a, b) => a.groupType === b.groupType ? 0 : a.groupType > b.groupType ? 1 : -1);
Also, in switch case you need to push the component and not a function.
case "grid":
lists.push(<GridView group={group} />);
break;
Need to use destructuring here const ListView = ({ group }) => {}
Finally add key to your lists. I have added using the item name, but you need to change per your requirement.

ReactJS two way binding not working, somewhere wrong with binding

I'm new to reactJs, I'm not sure where it went wrong.
I suppose there is something wrong with binding input. I suppose, cant change input because of value={detail.name}. However, even though I have deleted value={detail.name}, Name: {detail.name} still keeps the original value.
Could somebody give me a hint?
import React, { Component } from "react";
import "./App.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
details: [
{ id: 1, name: "Tom", age: "20" },
{ id: 2, name: "zhunan", age: "22" },
{ id: 3, name: "kobe", age: "35" }
]
};
}
changeName(event) {
this.setState({
name: event.target.value
});
}
onDelete() {}
render() {
return (
<div>
<ul>
{this.state.details.map((detail, index) => (
<li key={index}>
Name: {detail.name} | age: {detail.age}
<input
style={{ marginLeft: "10px" }}
type="text"
onChange={this.changeName.bind(this)}
value={detail.name}
/>
</li>
))}
</ul>
</div>
);
}
}
export default App;
I updated the code a bit.
First of all, I moved the binding of the callback to the constructor (to have ONE callback instead of one per item*render)
I also changed the key used in the map to be the id, rather than the index of the current item.
Try, it, I hope it works for you.
import React, { Component } from "react";
import "./App.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
details: [
{ id: 1, name: "Tom", age: "20" },
{ id: 2, name: "zhunan", age: "22" },
{ id: 3, name: "kobe", age: "35" }
]
};
this.changeName = this.changeName.bind(this);
}
changeName(event) {
const {target} = event;
const id = Number(target.dataset.id);
const { details } = this.state;
this.setState({
details: details.map((detail) => {
if (detail.id === id) {
return {
...detail,
name: target.value,
}
}
return detail;
}),
});
}
onDelete() {}
render() {
return (
<div>
<ul>
{this.state.details.map(({ id, age, name }) => (
<li key={id}>
Name: {name} | age: {age}
<input
style={{ marginLeft: "10px" }}
type="text"
onChange={this.changeName}
data-id={id}
value={name}
/>
</li>
))}
</ul>
</div>
);
}
}
export default App;
Your code works fine, nothing wrong with the input data binding. The problem is you're setting the name property directly to the state object. That would make it go from this:
this.state = {
details: [
{ id: 1, name: "Tom", age: "20" },
{ id: 2, name: "zhunan", age: "22" },
{ id: 3, name: "kobe", age: "35" }
]
}
To this:
this.state = {
details: [
{ id: 1, name: "Tom", age: "20" },
{ id: 2, name: "zhunan", age: "22" },
{ id: 3, name: "kobe", age: "35" }
],
name: "Bob"
}
Which has no effect on how the component gets rendered. To properly change the name of one of the details, which is what I assume you want, you also need to do a find that detail object to modify. Like this:
changeName(e, target_detail) {
this.setState({
// always update the WHOLE STATE OBJECT! using a map
details: this.state.details.map(detail => {
// the detail we want to modify has the same ID
if(detail.id === target_detail.id) {
// modify the name value of only that
target_detail.name = e.target.value
}
})
});
}
render method:
render() {
return (
<div>
<ul>
{this.state.details.map((detail, index) => (
<li key={index}>
Name: {detail.name} | age: {detail.age}
<input
style={{ marginLeft: "10px" }}
type="text"
// arrow functions implicitly "bind" the current this context:
onChange={e => this.changeName(e, detail)}
value={detail.name}
/>
</li>
))}
</ul>
</div>
);
}

Display array value with multiple objects

I need to display the values in my UsersData array, same as array numbers, but I can not do that in ReactJS.
Here's an example available in CodeSandbox.
https://codesandbox.io/s/n08n2m7mpj
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const usersData = [
{
total: 3,
data: [
{ id: 1, name: "Tania", username: "floppydiskette" },
{ id: 2, name: "Craig", username: "siliconeidolon" },
{ id: 3, name: "Ben", username: "benisphere" }
]
}
];
const numbers = [1, 2, 3, 4, 5];
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{numbers.map((number, index) => (
<li key={index}>{number}</li>
))}
{usersData.length > 0 ? (
usersData.map((data, index) => <div key={index}>Nome: {data.name}</div>)
) : (
<div>No users </div>
)}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
1) usersData is an array containing one element (an object)
2) You need to iterate over the data array of that object and display the value of name property for each its objects.
{usersData[0].data.length > 0 ? (
usersData[0].data.map((obj, index) => <div key={index}>Nome: {obj.name}</div>)
) : (
<div>No users </div>
)}
Forked update
Your usersData is an array usersData=[] which contains an object usersData=[{}] which itself contains the array of data usersData=[{data: []}] so you need to change your variable to an object and use the map function on the array of data inside it like so
const usersData = {
total: 3,
data: [
{ id: 1, name: "Tania", username: "floppydiskette" },
{ id: 2, name: "Craig", username: "siliconeidolon" },
{ id: 3, name: "Ben", username: "benisphere" }
]
};
and your loop would become
{usersData.data.length > 0 ? (
usersData.data.map((user, index) => <div key={index}>Nome: {user.name}</div>)
) : (
<div>No users </div>
)}
You need to do
usersData[0].data.map(({name}, index) => <div key={index}>Nome: {name}</div>)
Becaise you are not accessing the data array in your code above
usersData.map((userData, index) => {
return userData.data.map(item => {
return <div key={index + item.id}>Nome: {item.name}</div>;
});
});

Categories

Resources