How to use mapping in React JS for Image - javascript

Hi guys so I'm trying to make some web page about hotel room information using React JS and I wanted to change the name, description, image of the page depending on the room type the user choose. But I don't know how to map the image, can somebody help me to do the mapping ?
I haven't make the button tag to change the room type yet.
Here's my room.js code:
import React from 'react'
import {Row, Col, Container} from "react-bootstrap"
const RoomInfo = [
{
MainPhoto:"",
RoomType:"Superior Twin",
RoomDescription:"",
LittlePhoto:'Photo1.jpg'
},
{
MainPhoto:"",
RoomType:"Double Room Twin",
RoomDescription:"",
LittlePhoto:'Photo1.jpg'
},
]
const Room = () => {
return (
<>
<Container fluid={true} className="p-0">
<Row>
<Col>
<h1 className="text-center"> Check out our room</h1>
</Col>
</Row>
</Container>
</>
)
}
export default Room

I hope I understand your question correctly.
you can do <img src={variable} /> and than assign the variable the link to the picture.

You can using map array like this to render element from an array:
...
<h1 className="text-center"> Check out our room</h1>
{
RoomInfo.map((item, i) => {
return (
<div key={i}>
<img src={item.LittlePhoto} />
</div>
);
});
}
...

Related

How to add an emoji button in react?

So I already did this basically 1 year ago but I forgot how to do it, and its not working now though. Here is the LINK
basically I have a like a "smile emoji icon button" and then when I click it I will pass the emoji in my text but it giving me now an error undefined. In the link you can see that it has same thing here.
import './App.scss';
import React, { useState } from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
import Picker from 'emoji-picker-react';
function App() {
const [chosenEmoji, setChosenEmoji] = useState(null);
const onEmojiClick = (event, emojiObject) => {
setChosenEmoji(emojiObject);
console.log(emojiObject)
};
return (
<div className="App">
<header className="App-header">
{/* {isLogin && user ? <LoginTrue/> : <LoginFalse/>} */}
{chosenEmoji ? (
<span>You chose: {chosenEmoji.emoji}</span>
) : (
<span>No emoji Chosen</span>
)}
<Picker onEmojiClick={onEmojiClick} />
</header>
</div>
);
}
export default App;
but the new update of emoji-picker-react did get different...Is anyone can give me an idea of it? or is there another source of importing emojis..I don't want to use Input-emoji-react its too ugly.
You may find it helpful but the way I personally did it on my project were I also used emoji-picker-react and MaterialUI is through native materialUI emoji icon button like this:
<div className="chat_footer">
{!emojiPicker ? (
<InsertEmoticonIcon onClick={() => setEmojiPicker((prev) => !prev)} />
) : (
<>
<InsertEmoticonIcon
onClick={() => setEmojiPicker((prev) => !prev)}
/>
<EmojiPicker
searchDisabled="true"
previewConfig={{ showPreview: false }}
emojiStyle="google"
onEmojiClick={(e) => setInput((input) => input + e.emoji)}
height={400}
width="40%"
/>
</>
)}
As I said, InsertEmoticonIcon is a MaterialUI icon which I import
Code sandbox link:
This link may help:
https://codesandbox.io/s/emoji-picker-react-4-forked-h846rd?file=/src/App.tsx
Onclick handler has to be Emoji and Event, not Event and then emoji

Element type invalid

I am trying to loop out some partner logos from a headless CMS, but whenever I try to use React-components in my file I get an error stating
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `Partners`.
I can use my map functions as pure javascript functions but when I try to use them as React components I get this error.
What I want to work
const SinglePartner = ({partner}) => {
return (
<Col sm="6" md="3" lg="4" className="logoScaling">
<h4 className="text-center">{partner.title}</h4>
<img
src={partner.partnerLogo.asset.url}
alt={partner.partnerLogo.alt}
className="partnerLogos"
/>
</Col>
) }
const PartnerLooper = partners.map((partner) => {
return <SinglePartner key={partner._key} /> })
When debugging I tried simplifying my components, re-writing my PartnerLooper to
const PartnerLooper = partners.map((partner) => {
return <p>{partner.name}</p>
})
Using this method I can call PartnerLooper as a javascript function but not as a react component
return(
{/* Returns errror */}
<PartnerLooper />
{/* Works */}
{PartnerLooper}
)
Full component code:
import React from "react";
import { Col, Row } from "react-bootstrap";
const Partners = ({ partners }) => {
const PartnerLooper = partners.map((partner) => {
return <SinglePartner partner={partner} />
})
const SinglePartner = ({partner}) => {
return (
<Col sm="6" md="3" lg="4" className="logoScaling">
<h4 className="text-center">{partner.title}</h4>
<img
src={partner.partnerLogo.asset.url}
alt={partner.partnerLogo.alt}
className="partnerLogos"
/>
</Col>
)
}
return (
<div className="container pt-8 pt-md-10 partnerPadding" role="region">
<section aria-label="Partners">
<Row className="justify-content-md-center">
<PartnerLooper />
</Row>
</section>
</div>
);
};
export default Partners;
See the datastructure I am working with here
https://pastebin.com/MFGh1xuY
EDIT: I am running "gatsby": "^2.22.15" and "react": "^16.12.0",
You're assigning an array of elements to PartnerLooper and then using it as a component <PartnerLooper/> in the Partners component. you can insert an element array directly as a child in JSX.
Replace the returned JSX with
<div className="container pt-8 pt-md-10 partnerPadding" role="region">
<section aria-label="Partners">
<Row className="justify-content-md-center">
{PartnerLooper}
</Row>
</section>
</div>
If you meant to render one Row per partner, <ou can achieve that like this:
return (
<div className="container pt-8 pt-md-10 partnerPadding" role="region">
<section aria-label="Partners">
{partners.map(partner =>
<Row className="justify-content-md-center" key={partner._key}>
<SinglePartner partner={partner} />
</Row>
)}
</section>
</div>
)
Thank you DustInCompetent, your answer helped me
I did not want to run map directly in JSX because I think it is a bit ugly, I solved this by wrapping my SinglePartner and PartnerLooper-components in a parent component and using the return from this component. Full code:
const Partners = ({ partners }) => {
const AllPartners = () => {
const SinglePartner = ({ partner }) => {
return (
<Col sm="6" md="3" lg="4" className="logoScaling">
<h4 className="text-center">{partner.name}</h4>
<img
src={partner.partnerLogo.asset.url}
alt={partner.partnerLogo.alt}
className="partnerLogos"
/>
</Col>
)
}
const PartnerLooper = partners.map((partner) => {
return <SinglePartner partner={partner} />
})
return PartnerLooper
}
return (
<div className="container pt-8 pt-md-10 partnerPadding" role="region">
<section aria-label="Partners">
<Row className="justify-content-md-center">
<AllPartners />
</Row>
</section>
</div>
);
};
export default Partners;

filtering out onClick from a mapped array

I am trying to figure out how to filter out a mapped array and making the rest of the results disappear in the same component. I've done the same with React Router as I can route the result to a different page but I am wondering if there is a way to do the same on the same component? I have a Directory component (below) that is mapping through an array to display results of items on the page.
I would like to click on one of the elements and remove the rest. I tried to incorporate a filter method in the same component but drawing blanks on how I should implement it. Let me know what you think!
import React from 'react'
import { Card, CardImg} from 'reactstrap'
function Presentational({example, onClick}){
return(
<Card onClick={()=> onClick(example.name) }>
<CardImg src={example.image}/>
</Card>
)
}
function Directory(props){
const examples = props.propExample.map(example=>{
return (
<div>
<Presentational example={example} onClick={props.onClick} />
</div>
)
})
return(
<div>
{examples}
</div>
)
}
export default Directory;
You may use useState hook for selection
We store clicked elements inside the state variable selected. using useState hook.
When the user clicks on the element react component will remember which element he clicked and will render an array from 1 clicked element [selected].
In order to cleanup selection, just call setSelected()
It is the same logic as you want.
import React, {useState} from 'react'
import { Card, CardImg} from 'reactstrap'
function Presentational({example, onClick}){
return(
<Card onClick={()=> onClick(example.name) }>
<CardImg src={example.image}/>
</Card>
)
}
function Directory(props){
const [selected, setSelected] = useState()
const examples = (selected ? [selected] : props.propExample).map(example=>{
return (
<div>
<Presentational example={example} onClick={(name) => {
props.onClick(name)
setSelected(example)
}}
/>
</div>
)
})
return(
<div>
{examples}
</div>
)
}
export default Directory;
if you want to do it with a filter clause it will look almost the same, but with the extra operations
import React, {useState} from 'react'
import { Card, CardImg} from 'reactstrap'
function Presentational({example, onClick}){
return(
<Card onClick={()=> onClick(example.name) }>
<CardImg src={example.image}/>
</Card>
)
}
function Directory(props){
const [selected, setSelected] = useState()
const examples = props.propExample.filter(it => typeof selected === 'undefined' || it.name === selected).map(example=>{
return (
<div>
<Presentational example={example} onClick={(name) => {
props.onClick(name)
setSelected(name)
}}
/>
</div>
)
})
return(
<div>
{examples}
</div>
)
}
export default Directory;

Decoupling delete modal from button?

I've put together a sample I am working on where I want to decouple my dialogue Modal from the delete button. I'm running into trouble trying to think of how I can restructure the components while still keeping functionality. Ideally the modal should be rendered once and be modular. Data passed into it should change during the request to show the modal.
https://stackblitz.com/edit/react-l8hbdr
Right now I believe a delete modal is created for every single button which is horribly inefficient. I've heard using references are bad and using Redux for this seems overkill. Maybe I should use a React portal?
Where should the modal be rendered from? I'd like a reusable modal and I found this guide, however I don't know where I should be storing the Modal component and how data should pass into it.
There is a problem with props drilling in your code
For example, expenses and updateExpenses are passed from <Main /> to DisplayExpenses and then passed to <DeleteExpense />, if the app is getting bigger, this will make the code hard to maintain. I think you can put const [expenses, updateExpenses] = React.useState(...) from <Main /> to <DisplayExpenses />.
import React from 'react'
import { Col, Card, Row, Button } from "antd";
import uuid from 'react-uuid'
import 'antd/dist/antd.css';
import addExpense from '../utilities/AddExpense';
import DeleteExpense from '../utilities/DeleteExpense';
const Sentencer = require('sentencer');
export default function DisplayExpenses(props) {
// move expenses from <Main /> to <DisplayExpenses />
const [expenses, updateExpenses] = React.useState([
{
"id": uuid(),
"name": Sentencer.make("{{ noun }}"),
"amount": 53.22,
},
{
"id": uuid(),
"name": Sentencer.make("{{ noun }}"),
"amount": 76.16,
},
{
"id": uuid(),
"name": Sentencer.make("{{ noun }}"),
"amount": 716.16,
},
]);
const ListOfExpenses = () => {
return expenses.map((index) => {
return (
<Col key={index.id}>
<Card
key={index.id}
title={index.name}
bordered={true}
style={{ width: "100%", border: "1px solid black" }}
actions={[
<DeleteExpense
key={index.id}
id={index.id}
name={index.name}
amount={index.amount}
updateExpensesFn={updateExpenses}
expenses={expenses} />
]}
>
<p key={index.id}>Amount: {index.amount}</p>
</Card>
</Col>
)
})
}
return (
<>
<Row gutter={[16, 8]}>
<ListOfExpenses />
<Button
type="primary"
style={{ margin: "5% 5%" }}
onClick={() => addExpense({ expenses, updateExpensesFn: updateExpenses})}
>
Add Expense
</Button>
</Row>
</>
);
}
if you want to render <DeleteModal /> only once instead of every single button, you can adjust <DeleteExpense /> slightly, make <DeleteModal /> rendered only when modalVisibleBool is true
{modalVisibleBool && (
<DeleteModal
showModal={modalVisibleBool}
onOkay={() => onConfirmDelete({
updateExpensesFn: props.updateExpensesFn,
expenses: props.expenses,
expenseToDelete
})}
cancelFn={() => onCancelDeleteModal()}
expenseToDelete={expenseToDelete}
/>
)}

filter table by value with react redux and firebase

I am trying to filter a table in a react component by a value inside a document in firebase.
The important code looks like this. Claims is being parsed into another component for the table rows.
class Claims extends Component {
componentDidMount() {
this.props.getClaims();
}
render() {
const { Claims, loading } = this.props.data;
let recentClaimsMarkup = !loading ? (
Claims.map(Claim => <ClaimsTable Claim={Claim} />)
) : (
<p>Loading...</p>
);
return (
<Grid>
<Paper className = {mergeClasses.root}>
<Typography> {this.props.match.params.Project} Claim's</Typography>{" "}
</Paper>
<Paper className={mergeClasses.root}>
<Table className={mergeClasses.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Claim ID</TableCell>
<TableCell align="right">Date received</TableCell>
<TableCell align="right">Progress</TableCell>
<TableCell>Edit Claim</TableCell>
</TableRow>
</TableHead>
<TableBody>{recentClaimsMarkup}</TableBody>
</Table>
</Paper>
I am wanting to filter it by the url Project, shown below
{this.props.match.params.Project}
This is due to the claims being tied to the project name.
If this was in Python I would just use a for loop or something similar, but a little bit confused how to filter what Claims are able to be mapped.
Basically want it to be, for claims with Project == {this.props.match.params.Project}: map claims.
Appreciate any help :)
Thanks
So basically filter also returns a new copy of array and you can read more here, but the problem is you can't create the jsx element, if you want to know more
you can read this question
so in your case you need to first filter and then you need to render the jsx element using map like shown below
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from "react-router-dom";
import "./styles.css";
const User = props => {
const claimsUserHasAccess = props.data.claims.filter(
claim => claim.project === props.match.params.access
);
return (
<>
{claimsUserHasAccess.map(claim => (
<p key={claim.name}>{claim.name}</p>
))}
</>
);
};
const userData = {
claims: [
{ project: "enabled", name: "job" },
{ project: "enabled", name: "nick" },
{ project: "disabled", name: "jef" }
]
};
function App() {
return (
<div className="App">
<BrowserRouter>
<Route
path="/user/:access"
render={props => <User data={userData} {...props} />}
/>
</BrowserRouter>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
in the url you need to enter enabled or disabled to see the users. I hope this will give a better view of your problem.
working codesandbox

Categories